http://qs321.pair.com?node_id=948627

kazak has asked for the wisdom of the Perl Monks concerning the following question:

Hi to all . I tried to make a simple and extensible skeleton ( sentinel.pl) , simple enough ( I'm new to perl), and extensible enough for me to be able to extend this script. The first task was to watch over two background scripts( greylister.pl, repeater.pl). It seems like daemon works, and death of any of background scripts is detectable for script, but one thing looks odd for me. Sentinel.pl is able to start greylister.pl\repeater.pl only if they weren't running at the moment of sentinel's first start, but if any of scripts will die later when sentinel.pl is running, this event is logged but scripts ( repeater\greylister) are not restarted.
#!/usr/bin/perl -w # Watchdog daemon, made for watching and restarting of all system elem +ents. use warnings; use POSIX; use File::Pid; use Proc::Background; use POSIX qw(setsid); use lib '/etc/squid/repeater/lib/HTTP'; my $daemonName = "sentinel"; my $dieNow = 0; my $SleepMainLoop = 5; my $logging = 1; my $logFilePath = "/var/log/"; my $logFile = $logFilePath . $daemonName . ".log"; my $pidFilePath = "/var/run/"; my $pidFile = $pidFilePath . $daemonName . ".pid"; my $greylister = Proc::Background->new('/etc/squid/all_ban.pl'); my $repeater = Proc::Background->new('/etc/squid/repeater/lib/repeater +.pl'); chdir '/'; umask 0; open STDIN, '/dev/null' or die "Can't read /dev/null: $!"; open STDOUT, '>>/dev/null' or die "Can't write to /dev/null: $!"; open STDERR, '>>/dev/null' or die "Can't write to /dev/null: $!"; defined( my $pid = fork ) or die "Can't fork: $!"; exit if $pid; POSIX::setsid() or die "Can't start a new session."; $SIG{INT} = $SIG{TERM} = $SIG{HUP} = \&signalHandler; $SIG{PIPE} = 'ignore'; my $pidfile = File::Pid->new( { file => $pidFile, } ); $pidfile->write or die "Can't write PID file, /dev/null: $!"; if ($logging) { open LOG, ">>$logFile"; print LOG "Sentinel started.\n"; select((select(LOG), $|=1)[0]); } until ($dieNow) { sleep($SleepMainLoop); if (!$repeater->alive()) { logEntry ("Repeater isn't running, attempting to restart") +; $repeater = Proc::Background->new('/etc/squid/repeater/lib/ +repeater.pl'); } if (!$greylister->alive()) { logEntry ("Greyliter isn't running, attempting to res +tart"); $greylister = Proc::Background->new('/etc/squid/all_b +an.pl'); } } sub logEntry { my ($logText) = @_; my ( $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst ) + = localtime(time); my $dateTime = sprintf "%4d-%02d-%02d %02d:%02d:%02d", $year + 190 +0, $mon + 1, $mday, $hour, $min, $sec; if ($logging) { print LOG "$dateTime $logText\n"; } } sub signalHandler { $dieNow = 1; } END { if ($logging) { close LOG } $pidfile->remove if defined $pidfile; }

Replies are listed 'Best First'.
Re: Perl watcher daemon
by Crackers2 (Parson) on Jan 18, 2012 at 22:27 UTC
    if (system(@args1) != 0) { logEntry ("No repeater.pl is running, attempting to re +start"); $repeater; }

    I don't think that's doing what you think it does. As far as I can tell the bare $repeater doesn't do anything. You probably want something like

    if (system(@args1) != 0) { logEntry ("No repeater.pl is running, attempting to re +start"); $repeater = Proc::Background->new('/etc/squid/repeater +/lib/repeater.pl'); }

    Also, Proc::Background has functions for checking whether or not the process is still running, so you may want to use those instead of shelling out to pgrep:

    if (!$repeater->alive()) { logEntry ("No repeater.pl is running, attempting to re +start"); $repeater = Proc::Background->new('/etc/squid/repeater +/lib/repeater.pl'); }

    Of course that would not detect a process that was already started when your watcher begins. (But in that case you'd currently have 2 running processes anyway since you unconditionally start one with the initial Proc::Background->new call.)

      Thank you so much Crackers2 , now it works as a charm.
Re: Perl watcher daemon
by JavaFan (Canon) on Jan 18, 2012 at 21:52 UTC
    You know, you could just use make a respawn entry in your inittab.
      Respawn is not quite what I need, because only the first task is about restarting some scripts, other tasks will be much more complex.