Reputation: 47
I am seeing two issues with my Perl script:
My if
condition that has ==
, .
, !=
etc. is failing
The ps -p $pid -o etime=
throws an error sh: line 1: -o: command not found
I am trying to check whether a process is already running, and if so
If it has been running for more than 40 minutes then kill the process
If it has been running for 30-40 minutes then issue a notification
If it has been running for less than 30 minutes then exit
A simple if
test fails too. I have attached example code at the end.
Could some one please let me know the cause of these issues?
if ( `ps -ef | grep example | grep -v grep` ) {
print "Process is already running\n";
my $pid = `ps -ef | grep example | grep -v grep | awk '{print \$2}'`;
if ( `ps -p $pid -o etime= | sed -e "s/:/\\n/g" | wc -l | grep 3` ) {
print "1. Running for more than 40 mins\n";
`ps -ef | grep example | grep -v grep | awk '{print \$2}' | xargs kill -9`;
}
elsif ( `ps -p $pid -o etime= | sed -e "s/:/\\n/g" | wc -l|grep "2"` ) {
my $pmin = `ps -p $pid -o etime= | awk -F: '{print \$1}'`;
if ( $pmin < 30 ) {
print "Process running for 15 mins. Exiting";
exit;
}
elsif ( $pid >= 40 ) {
print "2.Running for more than 40 mins\n";
`ps -ef | grep example | grep -v grep | awk '{print \$2}' | xargs kill -9`;
}
else {
print "Process running for 30 mins. Notify";
}
}
}
my $psc = `ps -ef | grep example | grep -v grep >/dev/null 2>&1 && echo "Yes" || echo "No"`;
print "PSC - $psc";
if ( $psc eq "Yes" ) {
print "running";
}
else {
print "not running";
}
PSC - Yes
not running
Upvotes: 0
Views: 113
Reputation: 16
Try the below change
ps -A | grep firefox >/dev/null 2>&1 && echo "Yes" || echo "No"
Upvotes: 0
Reputation: 53508
I think this might be the root of your problem:
elsif ($pid >= 40) {
Because that's the process ID. Not $pmin
. So you're basically killing and process ID >40, which will be almost any process, apart from occasionally if it randomly gets a low pid.
But pretty fundamentally - shelling out to ps
and grep
is painful. Replacing :
with \n
and then counting lines is a bit of a nasty thing to do - and then using grep
to match a string is also pretty dirty.
Why not rewrite using something like Proc::ProcessTable
instead?
Here's an example of how you'd read the process table, find a particular process id (or set of) and then query the time:
#!/usr/bin/env perl
use strict;
use warnings;
use Proc::ProcessTable;
use Data::Dumper;
my $ps = Proc::ProcessTable->new;
my @target_processes = grep { $_->pid eq $$ } @{ $ps->table };
print Dumper \@target_processes;
sleep 10;
while (1) {
foreach my $process ( grep { $_->cmndline =~ m/perl/ } @{ $ps->table } ) {
sleep 5;
print $process ->cmndline, " has been running for ",
$process->time / 10000, "s\n";
print Dumper \$process;
}
}
Note - the time
is a high res time
Upvotes: 4