This Perl script was initially written about 3 or 4 years ago, but still does its daily job: monitor that certain processes are running and if not, restart them (plus send out a notification).
The script should run as the root user (since it will be restarting services or processes), and can easily be configured as a cron job.
Let’s say you’ve saved your script in /root/bin/services_watchdog.pl
, then the cronjob could look like:
# Check if main services are still running */5 * * * * /root/bin/services_watchdog.pl
This will check every 5 minutes if all required processes are running.
The script itself will start with:
#!/usr/bin/perl use strict; use warnings; use Proc::ProcessTable;
The script uses Proc::ProcessTable to retrieve a full process list.
The processes it should monitor, are easily defined in a hash:
my %services_table = ( 'MySQL' => { 'cmd' => '/etc/init.d/mysql restart', 're' => '/usr/sbin/mysqld --basedir=/usr', }, 'Postfix' => { 'cmd' => '/etc/init.d/postfix restart', 're' => '/usr/lib/postfix/master', }, # ... );
The actual processing of the process list can be done in a minumum of lines:
my %nok_services = %services_table ; my $services = join '|', map {$services_table{$_}->{'re'}} keys %services_table; my $process_table = Proc::ProcessTable->new; foreach my $process ( @{ $process_table->table } ) { if($process->cmndline =~ m/($services)/) { my $proc_name = (grep { $1 =~ m/Q$services_table{$_}->{'re'}E/} keys %services_table)[0]; delete $nok_services{$proc_name} if exists($nok_services{$proc_name}); $services = join '|', map {$services_table{$_}->{'re'}} keys %services_table; } }
Finally, the script tries to restart the missing service and prints a log message:
foreach my $process (keys %nok_services) { print "$process NOT running! Restarting...n"; system($nok_services{$process}->{'cmd'}); if ($? == -1) { print "failed to execute: $!n"; } elsif ($? & 127) { printf "child died with signal %d, %s coredumpn", ($? & 127), ($? & 128) ? 'with':'without'; } else { printf "child exited with value %dn", $? >> 8; } }
And that’s all folks!