Perl to check a process is running
I had to write a perl script today to check if a process is still running and launch it again if it wasn’t.
The code is pretty simple (and a bit on the dirty side) but get’s it done!
#!/usr/bin/perl
use strict;
my $path = shift; #path to script should we need to relaunch it
my $scriptName = shift; #name of script to look for
my $cmd = "ps aux | grep " . $scriptName;
my $result = `$cmd`;
my @lines = split("\\n", $result);
foreach(@lines) {
#ignore results for the grep command and this script
unless ($_ =~ m/grep|launcher/){
exit;
}
}
my $launchCMD = "cd $path; nohup ./$scriptName &";
system($launchCMD);
It assumes that it’s name is launcher.pl (if you use this and change the name make sure that the regex at line 14 has the new name in it!)
To check if /home/dko/myScript.pl is running then type the following:
./launcher.pl /home/dko/ myScript.pl
… and before any smart people comment, there’s a reason that it cds to the same directory as the script before it runs it!
No warranty, no support contract… no problems (for me at least)
’til next time,
Dk0
Comments
5 Responses to “Perl to check a process is running”
Leave a Reply
Wow that’s super cool dude!
Would be great for some of the things we use here at work!
This is a handy Perl module to check to see if a drive is mounted. This is done via the proc filesystem which is available on all flavours of linux
Usage: CheckMount::isMounted({ mount => $srcMount });
Thanks for the handy tip to see if something’s mounted, here is a simple alternative along with usage:
#!/usr/bin/perl
#
# Checks the Proc Filesystem for a mounted mount point
# Returns 1 if the mount point is mounted else 0
#
sub mountedOn{
$checkThisMount = shift;
# Proc filesystem which tracks current mounts
# This shouldn’t change (on linux)
my $procMountFile = ‘/proc/mounts’;
# Open the proc mount file
open(FILE, “$procMountFile”);
while () {
chomp();
if (/$checkThisMount /){
@mnt=split / /;
return @mnt[1];
close(FILE);
}
}
close(FILE);
# Default to mount NOT found
return 0;
}
if (mountedOn(”/dev/sda1″)){
print mountedOn(”/dev/sda1″) . “\n\n”;
}else{
print “Not Mounted\n”;
}
if (mountedOn(”/dev/sdb1″)){
print “Mounted\n”;
}else{
print “Not Mounted\n”;
}
Thanks a lot for this script! I’ve been having issues with apache and sendmail crashing and wanted to cron a script to make sure they were always running. I used your script as a base and extended it to allow checking of multiple processes and added a logging feature as well. Hopefully it helps someone out!
#!/usr/bin/perl
use strict;
#——————————————————————————————-
#
# Customize these variables
#
# Set whether an action (i.e. system command) should be taken if a process is found to not be running.
# NOTE: Logging is determined solely by the logging variable (i.e. logging still happens if live is 0)
my $live = 1;
# Name of processes to make sure are running, along with commands to execute if they aren’t
my %processes = (
“apache2″, “/etc/init.d/apache2 start”,
“idontexist”, “some command to run”,
“sendmail-mta”, “/etc/init.d/sendmail start”
);
# Enable/disable logging the results of this script
my $logging = 1;
my $logfile = “/var/log/syschk.log”;
# Verbosity of logs:
# 0 -> only write to log when a process is not found
# 1 -> write to log for each process that’s checked, regardless of whether it’s found or not.
my $verbose = 1;
#——————————————————————————————-
if ( $logging ) { open FILE , “>>”.$logfile; }
# Declare some variables
my $sec = shift;
my $min = shift;
my $hour = shift;
my $mday = shift;
my $mon = shift;
my $year = shift;
my $wday = shift;
my $yday = shift;
my $isdst = shift;
my $datetime = shift;
my $process = shift;
my $command = shift;
my $foundProcess = 0;
while (($process, $command) = each(%processes)) {
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime(time);
$datetime = sprintf( “%4d-%02d-%02d %02d:%02d:%02d: “, $year+1900,$mon+1,$mday,$hour,$min,$sec );
if ( $logging ) { logit( $datetime ); }
if ( $logging && $verbose > 0 ) { logit( “Checking “.$process.”… ” ); }
$foundProcess = 0;
my $cmd = “ps -A | grep ” . $process;
my $result = `$cmd`;
my @pslines = split(”\\n”, $result);
foreach ( @pslines ) {
#ignore results for the grep command and this script
unless ($_ =~ m/grep|syschk/){
$foundProcess = 1;
}
}
if ( $foundProcess == 0 ) {
if ( $live ) { system ( $command ); }
if ( $logging ) { logit( $process.” not running! ” ); }
if ( $logging && $live ) { logit ( “Executing: “.$command ); }
if ( $logging ) { logit ( “\n” ); }
}
else {
# Things to do if the process was found (e.g. logs)
if ( $logging && $verbose > 0 ) { logit( “Found “.$process.” running.\n” ); }
}
}
if ( $logging ) { close FILE; }
sub logit{
if ($logging){
if ( -w $logfile ) {
print FILE “$_[0]”;
}
}
}
Great set of ideas here, the mount one I particularly like, I’ve previously used checks for an existing file on the filesystem, but that is a much more elegant solution
for checking for running processes, I quite like Proc::ProcessTable for the large amount of info it allows you to match on, I currently use the below sub in a number of systems for checking if a process is running, and to return the PID to start/stop said process from a web UI
sub check_status {
## find process ID and return running or stopped
use Proc::ProcessTable;
my ($user, $procname, $path) = @_;
my $uid = getpwnam($user);
my $t = new Proc::ProcessTable;
foreach my $p (@{$t->table}) {
if ($p->{’cwd’} =~ /$path/ && $p->{’uid’} =~ /$uid/ && $p->{’cmdline’} =~ $procname) {
return $p->{’pid’};
}
}
return 0;
}
### Usage
my $html = (&check_status($d->{’user’}, ’srcds_i’, $server->{’install_path’}) > 0 ? qq~{’sid’}”>Stop~ : qq~{’sid’}”>Start~,);