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