Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"
 
PerlMonks  

Help to monitor a PID

by lsvolo (Novice)
on Sep 13, 2016 at 09:02 UTC ( [id://1171643]=perlquestion: print w/replies, xml ) Need Help??

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

Hi, I am seeking some Perl wisdom. I have wrote a small perl script to monitor a process and output to a file for X amount of time in a Linux/Unix env.
use warnings; # Some Variables $pid = `pgrep -f '[a]bc'`; $msg = "Alive"; $timestamp = localtime(time); # Open file open $fh, '>>' , 'file.txt' or die ( "Could not open file! $!\n" ) ; # Loop Condition $i = 0; until ($i > 60) { if ($pid) { $timestamp = localtime(time); print $fh ("$pid , $timestamp , $msg\n"); $pid = `pgrep -f '[a]bc'`; }else{ $timestamp = localtime(time); print $fh ("No pid , $timestamp\n"); $pid = `pgrep -f '[a]bc'`; } $i = $i +1; sleep 10; } print $fh ("Time over , $timestamp\n"); close $fh;
Now I face two problems that I would need your kind help if possible. First is that the print outcome in the file is using two line instead of one
example: 9910 abc , Tue Sep 13 04:44:33 2016 , Alive
Second is that when the script is in "sleep 10" if I kill the PID the next print in the file will show that is still Alive. I have used IO::Handle and $|=1 to solve this but it didn't work. I don't use perl much possibly twice a year so apologies in advance if my questions are not appropriate. Any help will be much appreciate.

Replies are listed 'Best First'.
Re: Help to monitor a PID
by haukex (Archbishop) on Sep 13, 2016 at 10:14 UTC

    Hi lsvolo,

    As Cuhulain has already pointed out, the string $pid will have a newline at the end, which you can remove with chomp, e.g. chomp($pid); This won't help if pgrep happens to return multiple PIDs - in this case I would recommend assigning the return value of the backticks to an array - see the description of backticks in list context in Quote-Like Operators in perlop. I've given an example using join below.

    As for your second question, look at the order in which your loop is doing things: print the message, then get the status of the process, then sleep for 10 seconds, then repeat (print the message, etc.). That's why you're getting the old status. If you move the pgrep call to just before the print, then you'll get the most recent status.

    As a general suggestion, I'd strongly recommend you use strict, see for example Use strict and warnings. Although your code looks ok for now, strict will help avoid programming mistakes.

    Here's how I might write the same script; have a look and if you have any questions about understanding then feel free to ask. I'm using IPC::System::Simple's capturex function to replace the backticks (`...`).

    #!/usr/bin/env perl use warnings; use strict; use IPC::System::Simple 'capturex'; my @cmd = ('pgrep','-f','bash'); my $msg = "Alive"; my $outfile = 'file.txt'; my $count = 5; my $sleeptime = 1; open my $fh, '>>', $outfile or die "Could not open $outfile! $!"; for (1..$count) { my $timestamp = localtime(time); my @pids = capturex(@cmd); chomp(@pids); if (@pids) { print $fh join(',',@pids) . " , $timestamp , $msg\n"; } else { print $fh "No pid , $timestamp\n"; } sleep $sleeptime; } print $fh "Time over , ".localtime(time)."\n"; close $fh;

    Hope this helps,
    -- Hauke D

Re: Help to monitor a PID
by Cuhulain (Beadle) on Sep 13, 2016 at 09:44 UTC
    Let's say I have a process called 'abc'. The command:  pgrep -f 'abc' returns: 3184 A character dump (on Linux):  pgrep -f 'abc' | od -c shows:
    0000000 3 1 8 4 \n 0000005
    Spot the trailing new-line. To scrap the newline, read the Learning Perl article on Using Backquotes to Capture Output.
      Hi gods, Thank you for the reply and the link. I have used chomp to resolve the print outcome. Can you or someone also assist on my second question? Regards
Re: Help to monitor a PID
by Corion (Patriarch) on Sep 13, 2016 at 10:13 UTC

    As for your second question: After your sleep, you only update $pid after printing the message. Maybe consider always updating $pid directly after the sleep instead of updating it after printing in two parts of your program:

    $pid = `pgrep -f '[a]bc'`; ... until ($i > 60) { if ($pid) { $timestamp = localtime(time); print $fh ("$pid , $timestamp , $msg\n"); }else{ $timestamp = localtime(time); print $fh ("No pid , $timestamp\n"); } $i = $i +1; sleep 10; $pid = `pgrep -f '[a]bc'`; }
      Thank you both for you comments and the time spend to assist! Work fine now

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1171643]
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others studying the Monastery: (6)
As of 2024-04-24 12:34 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found