Simple Remote Monitor for Apache with Perl

| 3 Comments | 2 TrackBacks
| | | |
Sometime last week Apache on one of the servers that manages some websites I host stop responding to requests, resulting in said websites being unavailable for a day and half (or so). Unfortunately I didn't know about the problem until someone else notified me of the issue. Opps. Not good system administration that.


There are plenty of solutions for monitoring network services, but given that I'm just running Apache for a half dozen non-critical websites on the side, there's no reason to go overboard. Any sysadmin worth their weight in salt should be able to whip something up with Perl in no time.1 So, what's needed? Well, something that will remotely monitor the pool of websites and notify me if something is amiss:

monitor_flow.jpg

First up, making a simple HTTP GET request:

my $url = "http://$host";
my $ua = LWP::UserAgent->new;
my $response = $ua->get( $url );

Now we test the response, was it successful? If so, Apache returns an appropriate status code and the requested resource. If Apache is available, but unable to properly process the request it will responded with some relevant status code, which we wish to pass on for further troubleshooting:

if ( !$response->is_success ) {

	# Do we have an error code?
	if ( $response->code ) {

	     reportError("$host reports $response->message \n");

	} else {

However a failed GET request will result in no status code since Apache probably failed to respond at all. In this case it would be helpful to determine if the issue is with Apache or something else. For that test a network ping is issued:

		# HTTP is down, is the network connection down too?
		my $p = Net::Ping->new("icmp");
		if ( $p->ping( $host, 2 )) {

		     reportError ("$host is responding,
		     		     	     but Apache is not.\n");

		} else {

		     reportError ("$host is unreachable.\n");

		}
	}

Not too difficult that. Now, how do we go about communicating the issue at hand? SMS has always been my preferred method since my phone is usually close at hand and, iPhone or not, SMS is widely implemented and easy to use.

# Send SMS via cellular Email to SMS gateway
my ( $msg ) = @_;
my $to = "7735551234\@txt.att.net";
my $from = "pdw\@weinstein.org";
my $subject = "Service Notification";

my $sendmail = '/usr/lib/sendmail';
open( MAIL, "|$sendmail -oi -t" );
	print MAIL "From: $from\n";
	print MAIL "To: $to\n";
	print MAIL "Subject: $subject\n\n";
	print MAIL $msg;
close( MAIL ); 

All's done? Not quite. For the fun of it, I figured broadcasting a message that the server was unavailable might be of use to regular visitors. What better way to broadcast a short message than via Twitter?

my ( $msg ) = @_;
my $nt = Net::Twitter::Lite->new(
	username => $username,
	password => $password );

my $result = eval { $nt->update( $msg ) };

Bring this all together, with cron gives us:

# monitor remote httpd servers every 30 minutes
*/30 * * * *   pdw  /home/pdw/bin/monitor.pl >/dev/null 2>&1



#!/usr/bin/perl
use strict;

use LWP::UserAgent;
use Net::Ping;
use Net::Twitter::Lite;

my @hosts = ( "pdw.weinstein.org", "www.weinstein.org" );

foreach my $host ( @hosts ) {

my $url = "http://$host";
my $ua = LWP::UserAgent->new;
my $response = $ua->get( $url );

if ( !$response->is_success ) {

# Do we have an error code?
if ( $response->code ) {

reportError("$host reports
$response->message.\n");

} else {

# HTTP is down, is the network connection down too?
my $p = Net::Ping->new("icmp");
if ( $p->ping( $host, 2 )) {

reportError ( "$host is responding,
but Apache is not.\n" );

} else {

reportError ( "$host is unreachable.\n" );

}

}

}

sub reportError ($) {

my ( $msg ) = @_;
my $nt = Net::Twitter::Lite->new( username => $username, password => $pasword );
my $result = eval { $nt->update( $msg ) };

if ( !$result ) {

# Twitter has failed us,
# need to get the word out still...
smsEmail ( $msg );

}

}

sub smsEmail ($) {

my ( $msg ) = @_;
my $to = "7735551234\@txt.att.net";
my $from = "pdw\@weinstein.org";
my $subject = "Service Notification";

my $sendmail = '/usr/lib/sendmail';
open(MAIL, "|$sendmail -oi -t");
print MAIL "From: $from\n";
print MAIL "To: $to\n";
print MAIL "Subject: $subject\n\n";
print MAIL $msg;
close( MAIL );

}



1 Of course if I was worth my weight I would have had something in place long before it was called for....

2 TrackBacks

TrackBack URL: http://pdw.weinstein.org/mt/mt-tb.cgi/165

This post was mentioned on Twitter by pdweinstein: @linuxalive Simple Remote Monitor for Apache with Perl http://ow.ly/rEfN #linux #perl #apache Read More

A Simple Remote Monitor for Apache, Enhanced. Read More

3 Comments

Thank you in advance for your quick answer !. Very nice post.

I enjoyed reading this blog post! Keep up the fantastic operate.

I definitely appreciate your writing style. This really a wonderful post! Thanks!

Leave a comment

About the Author

Paul is a technologist and all around nice guy for technology oriented organizations and parties. Besides maintaining this blog and website you can follow Paul's particular pontifications on the Life Universe and Everything on Twitter.

   
   


Subscribe:
Add to Google Reader or Homepage
Add to My AOL

Add to netvibes
Subscribe in Bloglines
Add to Technorati Favorites

Powered
CentOS
Apache
MySQL
Perl
Movable Type Pro