Tibor's Musings

Apache Watchdog

An example how to fork Unix processes and set process group in order to write a simple Apache watchdog, connecting to a web page and eventually restarting web server when the web page does not respond within a given time limit.

#! /usr/local/bin/perl -w
## name: watchdog_httpd
## author: tibor.simko@cern.ch
## revision: 19990813
## description: checks if webserver is running okay by downloading a page
##  (if no response from the server is received in X secs => restart it)
## note: to be called from root's crontab each let us say 30 minutes

## -- configuration section starts here
$httpd_test="/soft/bin/wget -q --spider http://example.org/";
$httpd_test_timeout=6; # in seconds
$httpd_restart="/soft/bin/apachectl restart";
## -- configuration section ends here

###############################################
###  do not change anything below this line ###
###############################################

require "ctime.pl";
$now = &ctime(time);
chop($now);

umask 022;

unless ($pid = open CMD, "-|") {
    defined $pid || die "E: fork failed $!";
    setpgrp(0, $$) || die "E: set process group failed $!";
    exec $httpd_test || die "E: cannot execute httpd test query $!";
}
if (&timed_out($httpd_test_timeout, \*CMD)) {
    kill -1 => $pid;
    warn "W: test query timed-out, restarting httpd (", $now, ")\n";
    system $httpd_restart;
}
close CMD;
if ($?) {
    warn "W: test query failed, restarting httpd (", $now, ")\n";
    system $httpd_restart;
}

# some subroutines:

sub timed_out {
    my($timeout_secs, $handle) = @_;
    my $rin;
    vec($rin='', fileno($handle), 1) = 1;
    if (select $rin, undef, undef, $timeout_secs) {
        return '';
    }
    else {
        return 1;
    }
}