#!/usr/bin/perl use File::Basename; use strict; my $dir = shift; unless (-d $dir) { print "Arg is not a directory"; exit 1; } my $me = basename $dir; my ($status, $details); sub do_command { my $command = shift; $command =~ /^(\w+)(\s+(.*))?$/; my ($do, $args) = ($1, $3); if ($do eq 'mail') { open MAIL, '|-', qq!mail -s "$me $status" $args! or die "Could not mail"; print MAIL $details,"\n"; close MAIL; } elsif ($do eq 'exec') { system($args); } elsif ($do eq 'pipe') { open PIPE, '|-', $args; print PIPE "$status\n"; print PIPE $details; close PIPE; } } my ($checkcommand, $every, %on); $on{success} = []; $on{failure} = []; $on{change} = []; open CONFIG, "$dir/check"; while () { my @words = split(/\s+/); my $command = shift @words; if ($command eq 'check') { $checkcommand = join(' ', @words); } elsif ($command eq 'on') { my $when = shift @words; if ($when eq 'failure') { push @{$on{failure}}, join(' ', @words); } elsif ($when eq 'success') { push @{$on{success}}, join(' ', @words); } elsif ($when eq 'change') { push @{$on{change}}, join(' ', @words); } else { print "Unknown event in 'on', $dir/check line $.\n"; } } elsif ($command eq 'every') { $every = $words[0]; } else { print "Unknown command '$command', $dir/check line $.\n"; } } close CONFIG; unless ($checkcommand) { print "Check command not specified in $dir/check\n"; exit 1; } unless (@{$on{failure}} || @{$on{success}} || @{$on{change}}) { print "No actions specified in $dir/check. This is probably a mistake.\n"; } open STATUS, "$dir/checkstatus"; chomp(my $oldstatus = ); my $oldtime = (stat(STATUS))[9]; close STATUS; my $td = time() - $oldtime; if ($td < $every) { # Not time to recheck yet #print "Not rechecking; ", $every - $td, " seconds to go.\n"; exit $oldstatus; } my ($pid, $hung, $exitstatus); $SIG{ALRM} = sub { kill 9, $pid; $hung = 1; }; alarm 10; $pid = open CHECK, '-|', $checkcommand; $status = ; $details = join('', ); close CHECK; if ($hung) { $status = 'TIMEOUT'; $details = 'Check did not complete within ten seconds'; $exitstatus = -1; } else { $exitstatus = $? >> 8; } if ($exitstatus == 0 && $oldstatus != 0) { do_command($_) foreach @{$on{success}}; } if ($exitstatus != 0 && $oldstatus == 0) { do_command($_) foreach @{$on{failure}}; } if ($exitstatus != $oldstatus) { do_command($_) foreach @{$on{change}}; } open STATUS, ">$dir/checkstatus"; print STATUS "$exitstatus\n"; print STATUS "$status\n"; print STATUS "$details\n"; close STATUS; exit $exitstatus;