This code sample is a Daemon Watcher first developed by Tim Baker when we worked at Cox Interactive Media. I liked it so much I made some improvements here and there, and now use it as standard tool for all system installs. This version came straight from a Solaris 8 machine.
Generally the cron looks like
#Daemon checker 15,30,45,59 * * * * /admin/global/bin/check_daemon.pl >> /var/adm/log/check_daemon.log
Don't forget to rotate the logs this generates.
#!/bin/perl
# ========================================================================
# File : check_daemons.pl
# Purpose : Runs from cron.
# Author: Tim Baker & Mike Tremaine mgt-@@-stellarcore.net
# ========================================================================
# This is cron'd to run once every 15mins (0,15,30,45)
use strict;
&init_global();
#Check Daemons everytime we run
foreach my $daemon( keys %{ $global::daemons } ) {
&check_daemon( $daemon );
}
exit;
# ------------------------------------------------------------------------
# init_global() - setup the Lumberjack stream
#
# in : none
# out : none
# glob : Lots
# err : none
# notes : none
# ------------------------------------------------------------------------
sub init_global {
#Logs
$global::log_file = "check_daemon.log";
$global::log_dir = "/var/adm/log/check_daemon.log";
$global::run_dir = "/var/run";
#Commands
$global::p_rm = "/bin/rm";
$global::p_xargs = "/bin/xargs";
$global::p_find = "/bin/find";
$global::ps_cmd = '/bin/ps';
$global::ps_flags = '-f -p';
$global::grep_cmd = '/bin/grep';
$global::grep_flags = '';
#Daemon Config
# Info about the daemons to watch
$global::daemons = {
prngd => {
greptest => 'prngd',
pidfile => "$global::run_dir/prngd.pid",
command => "/etc/init.d/prngd start"
},
sshd => {
greptest => 'sshd',
pidfile => "$global::run_dir/sshd.pid",
command => "/etc/init.d/sshd start"
},
sendmail => {
greptest => 'sendmail',
pidfile => "$global::run_dir/sendmail.pid",
command => "/etc/init.d/sendmail start"
}
};
#Time values for functions
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
$year = $year + 1900;
$mon = $mon + 1;
if ($min < 10) { $min = "0" . $min; };
if ($mon < 10) { $mon = "0" . $mon; };
if ($mday < 10) { $mday = "0" . $mday; };
if ($hour < 10) { $hour = "0" . $hour; };
$global::timestamp = "[" . $mon . "/" . $mday . "/" . $year . " " . $hour . ":" . $min . " ]";
} # sub init_global
#######################################
#Check Daemons
sub check_daemon {
my $daemon = shift;
my $grep_test = $global::daemons->{$daemon}->{greptest};
my $pid_file = $global::daemons->{$daemon}->{pidfile};
# if there's a PID file , see if that process is running
if( open( PID, "< $pid_file" ) ) {
chomp( my $pid = );
close PID;
my $call = "$global::ps_cmd $global::ps_flags $pid | " .
"$global::grep_cmd '$grep_test' | $global::grep_cmd -v 'tail -f '";
my @daemons = grep { index( $_, 'grep' ) == -1 } `$call`;
# if it is running
if( (scalar @daemons) ) {
print "$global::timestamp daemon $daemon is running\n";
return;
}
else {
#make sure the daemon is not running under another PID
my $call = "$global::ps_cmd -ef | $global::grep_cmd '$grep_test' | " .
"$global::grep_cmd -v grep | $global::grep_cmd -v 'tail -f '";
my @daemons = `$call`;
if( (scalar @daemons) ) {
print "$global::timestamp daemon $daemon is running but PID file is wrong\n";
my $pid_restore = "$global::ps_cmd -ef | $global::grep_cmd '$grep_test' ".
"| $global::grep_cmd -v grep | $global::grep_cmd -v 'tail -f ' | awk '{ print \$2 }'";
`$pid_restore > $pid_file`;
print "$global::timestamp daemon '$daemon' $pid_file file created\n";
return;
} else {
print "$global::timestamp daemon '$daemon' is not running," .
"but it left a PID file behind\n";
# ...and restart the daemon
start_daemon( $daemon );
}
}
}
else {
# is there a daemon running without a pid file?
my $call = "$global::ps_cmd -ef | $global::grep_cmd '$grep_test' | " .
"$global::grep_cmd -v grep | $global::grep_cmd -v 'tail -f '";
my @daemons = `$call`;
# daemon is already running
if( (scalar @daemons) ) {
print "$global::timestamp daemon '$daemon' is running with no PID file\n";
#print @daemons;
#Be nice to make one -mgt
my $pid_restore = "$global::ps_cmd -ef | $global::grep_cmd '$grep_test'" .
"| $global::grep_cmd -v grep | $global::grep_cmd -v 'tail -f ' | awk '{ print \$2 }'";
`$pid_restore > $pid_file`;
return;
}
else {
print "$global::timestamp daemon '$daemon' is not running\n";
start_daemon( $daemon );
}
}
} # sub check_daemon
# ------------------------------------------------------------------------
# start_daemon() - start up a daemon
#
# in : the key of the daemon in the global daemons hash
# out : none
# mod : none
# glob : $global::daemons
# err : none
# notes : none
# ------------------------------------------------------------------------
sub start_daemon {
my $daemon = shift;
my $cmd = $global::daemons->{$daemon}->{command};
print "$global::timestamp restarting daemon '$daemon'\n";
system ( $cmd ) == 0 || do {
print "$global::timestamp Unable to spawn $cmd: $!\n";
return;
};
print "$global::timestamp daemon '$daemon' restarted\n";
} # sub start_daemon