<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Brian Wigginton &#187; Ruby</title>
	<atom:link href="http://www.bwigg.com/category/ruby/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.bwigg.com</link>
	<description>Lab and Nerdery</description>
	<lastBuildDate>Fri, 03 Feb 2012 04:15:48 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Ruby Script to Check Site Availability</title>
		<link>http://www.bwigg.com/2008/10/ruby-script-to-check-site-availability/</link>
		<comments>http://www.bwigg.com/2008/10/ruby-script-to-check-site-availability/#comments</comments>
		<pubDate>Tue, 07 Oct 2008 21:18:34 +0000</pubDate>
		<dc:creator>bawigga</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Scripts]]></category>

		<guid isPermaLink="false">http://www.bwigg.com/?p=39</guid>
		<description><![CDATA[Recently, I've been looking around for scripts to check the availability of websites I'm hosting, then email me a status message if there is anything I should be worrying about. There are many services out there, but none are free. Fortunately this kind of thing can be done with a little ruby script and cron [...]]]></description>
			<content:encoded><![CDATA[<p>Recently, I've been looking around for scripts to check the availability of websites I'm hosting, then email me a status message if there is anything I should be worrying about. There are many services out there, but none are free. Fortunately this kind of thing can be done with a little ruby script and cron job.</p>
<p>Requirements</p>
<ul>
<li>SMTP server.</li>
<li>Ruby 1.8.6 - This script uses core classes of Ruby and doesn't require any rubygems</li>
<li>Ability to add cron jobs to your machine</li>
</ul>
<p><strong>Plan</strong></p>
<p>Now, let's think out some solutions for how we can check on a site's availability. We could ping the server, but that only checks that the box is up and running. It doesn't necessarily mean that our HTTP Service is serving up pages correctly. We could use curl or wget to pull down the default page being served, but what if it's a holding space page, or a 404 error? This method would basically only tell us if the webserver is running or not, same as the ping method. Alternatively, we could test the to see what the response code of the page is. This way we can also find out what type of issue we are having on the server.</p>
<p>I also want this script to be a little more robust. Instead of having a hardcoded URL in my script,  I want it to pull a list of urls from a txt file. I also want each url report to be emailed to different email addresses since some of these sites are for work and some are personal.</p>
<p><strong>Checking the Response Codes</strong></p>
<p>There are lots of different response codes that we could receive from the server. The most familiar for anyone who's ever browsed the net is the infamous 404 Page Not Found error. Let's quickly take a look at what this error code means. Wikipedia states a 4** message means that "the request contains bad syntax or cannot be fulfilled.", in english, something went wrong on the web surfers side. This can be because of a mistyped URL or the result of a clicked link that took us to a page that's no longer available or has been moved. Now, the second two numbers tell us more specifically what kind of issue we've found, in our case *04, which Wikipedia explains as "The requested resource could not be found but may be available again in the future. Subsequent requests by the client are permissible." or in other words, it's lost, maybe only temporarily, but we can keep trying if we want.</p>
<p>Other response code groups include the following:</p>
<ul>
<li class="toclevel-1"><a href="http://en.wikipedia.org/wiki/List_of_HTTP_status_codes#1xx_Informational"><span class="tocnumber">1</span> <span class="toctext">1xx Informational</span></a></li>
<li class="toclevel-1"><a href="http://en.wikipedia.org/wiki/List_of_HTTP_status_codes#2xx_Success"><span class="tocnumber">2</span> <span class="toctext">2xx Success</span></a></li>
<li class="toclevel-1"><a href="http://en.wikipedia.org/wiki/List_of_HTTP_status_codes#3xx_Redirection"><span class="tocnumber">3</span> <span class="toctext">3xx Redirection</span></a></li>
<li class="toclevel-1"><a href="http://en.wikipedia.org/wiki/List_of_HTTP_status_codes#4xx_Client_Error"><span class="tocnumber">4</span> <span class="toctext">4xx Client Error</span></a></li>
<li class="toclevel-1"><a href="http://en.wikipedia.org/wiki/List_of_HTTP_status_codes#5xx_Server_Error"><span class="tocnumber">5</span> <span class="toctext">5xx Server Error</span></a></li>
</ul>
<p>I'm not really interested in being notified of anything that starts with a 2**, since that means the site is up and functioning correctly. 3** are redirect codes, these might be useful, but I don't really care about them. I should know if one of my sites is being redirected because I would have had to set it up that way. I am only going to check if the response code starts with a 2xx or 3xx, if it does then were fine and I dont need to be notified. If it doesn't, then there's an issue and I need to know about it.</p>
<p>To check the reponse code of the page, Ruby has a class in it's core called Net:HTTPResponse, which will go out and touch a URL and return the reponse code the server supplied.</p>
<p><strong>Sending the Email</strong></p>
<p>This script uses the Ruby class Net::SMTP, which allows communication with an SMTP server. On my box I have postfix setup, which runs on port 25. When I send the email I want to be notified which url went down and what the response code is. I also added the HTTP version in there just in case.</p>
<p><strong>Automatically Running the Script</strong></p>
<p>To get this script to run automatically, I'm going to need to setup a cron job. To create a cron job we need to add a line to our crontab file, which can be found at /etc/crontab.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># [minutes] [hours] [day of month] [month] [day of week] [user] [command]</span>
<span style="color: #000000;">0</span>,<span style="color: #000000;">15</span>,<span style="color: #000000;">30</span>,<span style="color: #000000;">45</span> <span style="color: #000000; font-weight: bold;">*</span> <span style="color: #000000; font-weight: bold;">*</span> <span style="color: #000000; font-weight: bold;">*</span> <span style="color: #000000; font-weight: bold;">*</span> bawigga ~<span style="color: #000000; font-weight: bold;">/</span>scripts<span style="color: #000000; font-weight: bold;">/</span>check_uptime.rb</pre></div></div>

<p>Above we can see that I set the script to run on the 0th, 15th, 30th, and 45th minute, of any (*) hour of any day of the month, of any month, of any day of the week, under the username bawigga, and we want to execute the check_uptime.rb script in my home/scripts directory.</p>
<p><strong>The Script</strong></p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#008000; font-style:italic;">#!/usr/bin/ruby</span>
&nbsp;
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'net/http'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'net/smtp'</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># Brian Wigginton</span>
<span style="color:#008000; font-style:italic;"># http://www.bwigg.com/2008/10/ruby-script-to-check-site-availability/</span>
<span style="color:#008000; font-style:italic;"># 10/7/2008</span>
<span style="color:#008000; font-style:italic;">#</span>
<span style="color:#008000; font-style:italic;"># Check's availabilty of a website. Needs to be run via a cron job.</span>
<span style="color:#008000; font-style:italic;"># Example cron job line to be placed in crontab</span>
<span style="color:#008000; font-style:italic;">#</span>
<span style="color:#008000; font-style:italic;"># 0,15,30,45 * * * * username ~/scripts/check_uptime.rb</span>
<span style="color:#008000; font-style:italic;">#</span>
<span style="color:#008000; font-style:italic;"># This script uses a txt file to look for urls and email addresses.</span>
<span style="color:#008000; font-style:italic;"># This text file needs to be in the following format</span>
<span style="color:#008000; font-style:italic;"># -- lines with beginning with # signs will be ignored</span>
<span style="color:#008000; font-style:italic;"># -- first thing should be the url</span>
<span style="color:#008000; font-style:italic;"># -- then a space</span>
<span style="color:#008000; font-style:italic;"># -- then email addresses seperated by commas, no white space.</span>
<span style="color:#008000; font-style:italic;"># EXAMPLE</span>
<span style="color:#008000; font-style:italic;">#       example.com admin@axample.com,bob@example.com</span>
&nbsp;
<span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#CC0066; font-weight:bold;">open</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;/home/user/scripts/sites.txt&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">each</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>line<span style="color:#006600; font-weight:bold;">|</span>
	<span style="color:#008000; font-style:italic;"># get rid of CRLF</span>
	line.<span style="color:#CC0066; font-weight:bold;">chomp!</span>
&nbsp;
	<span style="color:#9966CC; font-weight:bold;">next</span> <span style="color:#9966CC; font-weight:bold;">if</span><span style="color:#006600; font-weight:bold;">&#40;</span>line<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">0</span>..<span style="color:#006666;">0</span><span style="color:#006600; font-weight:bold;">&#93;</span> == <span style="color:#996600;">'#'</span> <span style="color:#006600; font-weight:bold;">||</span> line.<span style="color:#9900CC;">empty</span>?<span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
	url, emails = line.<span style="color:#CC0066; font-weight:bold;">split</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">' '</span><span style="color:#006600; font-weight:bold;">&#41;</span>
	emails = emails.<span style="color:#CC0066; font-weight:bold;">split</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;,&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
	<span style="color:#008000; font-style:italic;"># check if http:// was in the url if not add it in there</span>
	url.<span style="color:#9900CC;">insert</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">0</span>, <span style="color:#996600;">&quot;http://&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">unless</span><span style="color:#006600; font-weight:bold;">&#40;</span>url.<span style="color:#9900CC;">match</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">/</span>^http\:\<span style="color:#006600; font-weight:bold;">/</span>\<span style="color:#006600; font-weight:bold;">//</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
	<span style="color:#008000; font-style:italic;"># Get the HTTP_RESPONSE from the site we are checking</span>
	res = <span style="color:#6666ff; font-weight:bold;">Net::HTTP</span>.<span style="color:#9900CC;">get_response</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#CC00FF; font-weight:bold;">URI</span>.<span style="color:#9900CC;">parse</span><span style="color:#006600; font-weight:bold;">&#40;</span>url.<span style="color:#9900CC;">to_s</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
	<span style="color:#008000; font-style:italic;"># Check the response code and send an email if the code is bad</span>
	<span style="color:#9966CC; font-weight:bold;">unless</span><span style="color:#006600; font-weight:bold;">&#40;</span>res.<span style="color:#9900CC;">code</span> =~ <span style="color:#006600; font-weight:bold;">/</span><span style="color:#006666;">2</span><span style="color:#006600; font-weight:bold;">|</span><span style="color:#006666;">3</span>\d<span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006666;">2</span><span style="color:#006600; font-weight:bold;">&#125;</span><span style="color:#006600; font-weight:bold;">/</span> <span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">then</span>
		from = <span style="color:#996600;">&quot;admin@example.com&quot;</span>
		message = <span style="color:#996600;">&quot;From: admin@example.com<span style="color:#000099;">\n</span>Subject: #{url} Unavailable<span style="color:#000099;">\n</span><span style="color:#000099;">\n</span>#{url} - #{res.code} - #{res.message}<span style="color:#000099;">\n</span>HTTP Version - #{res.http_version}<span style="color:#000099;">\n</span><span style="color:#000099;">\n</span>&quot;</span>
		<span style="color:#9966CC; font-weight:bold;">begin</span>
			<span style="color:#6666ff; font-weight:bold;">Net::SMTP</span>.<span style="color:#9900CC;">start</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'localhost'</span>,<span style="color:#006666;">25</span> , <span style="color:#996600;">'example.com'</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>smtp<span style="color:#006600; font-weight:bold;">|</span>
			smtp.<span style="color:#9900CC;">send_message</span><span style="color:#006600; font-weight:bold;">&#40;</span>message, from, emails<span style="color:#006600; font-weight:bold;">&#41;</span>
		<span style="color:#9966CC; font-weight:bold;">end</span>
		<span style="color:#9966CC; font-weight:bold;">rescue</span> <span style="color:#CC00FF; font-weight:bold;">Exception</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> e
			<span style="color:#CC0066; font-weight:bold;">print</span> <span style="color:#996600;">&quot;Exception occured: &quot;</span> <span style="color:#006600; font-weight:bold;">+</span> e
		<span style="color:#9966CC; font-weight:bold;">end</span>
	<span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#006600; font-weight:bold;">&#125;</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://www.bwigg.com/2008/10/ruby-script-to-check-site-availability/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

