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

fellow monks,

I'm using scripted SSH access to launch a script on a remote server. I decided to break the remote scripts into two components. One script will do the heavy work, data collection, etc. The other script that's accessed via SSH will simply cat the collected results file. I needed a way to keep the two scripts from bumping into each other as each will either be reading or writing to the same remote data file.

After some experimentation, the following is what I came up with and is roughly equivalent at the beginning of each script. I found that without the match against a non-numeric value, the while loop would continue on...even if the other process had since exited and also when stating while($pid > 0). What am I missing? Thanks in advance for your insights and suggestions for improvement are also welcome.

#!/usr/bin/perl -w # # cat data obtained from collector script use strict; my $pid = `pgrep -f _collectDataScript.pl`; if ($pid) { while($pid) { print "Waiting for process $pid"; sleep(10); my $pid = `pgrep -f _collectDataScript.pl`; if ($pid !~ m/\d+/) { print "process id is non-numeric\n"; last; } } } print "process finished...do something\n";

Replies are listed 'Best First'.
Re: process management
by shmem (Chancellor) on Jun 12, 2007 at 21:31 UTC
    You need the /\d/ match because the inner my $pid masks the outer, which is the condition for your while loop to go on. Invoking pgrep inside the loop and assigning its output to $pid declared as my inside the loop doesn't change the value while() is looking at (the outer $pid).

    Drop the inner my:

    my $pid = `pgrep -f _collectDataScript.pl`; if ($pid) { while($pid) { print "Waiting for process $pid"; sleep(10); $pid = `pgrep -f _collectDataScript.pl`; } }

    Also note that the backticks yield the output of its command with a newline appended.

    --shmem

    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
Re: process management
by jasonk (Parson) on Jun 12, 2007 at 20:22 UTC

    Without knowing what the code looked like without the match, I'm guessing, but if you just remove the match and it's associated block, then you are using two different variables in different scopes both named $pid, the assignment just after the sleep will go out of scope at the end of that block, and the other $pid (which is the one the while is checking) will never change, so the loop will never end.

    If you remove the match block, and also remove the my from the assignment just before it then it should work, although I'd probably do it something like this instead...

    #!/usr/bin/perl -w # # cat data obtained from collector script use strict; while ( my $pid = `pgrep -f _collectDataScript.pl` ) { print "Waiting for process $pid"; sleep(10); }

    We're not surrounded, we're in a target-rich environment!
Re: process management
by pajout (Curate) on Jun 12, 2007 at 21:58 UTC
    I thought about similar issue before some time, but from different perspective. If some process (or, more exactly, some family of processes) will do a job to create some files, it can write origfilename.$pid, and rename that file when finished. The reading process will read only files without $pid postfix. For entireness, the reading process or other process should check writing process defined by $pid for existence, identity and sanity - but implementation of checking depends on particular requirement...
Re: process management
by Moron (Curate) on Jun 13, 2007 at 12:31 UTC
    There have got to be easier ways of signalling completion of the results file. One well-known way is to number them and create a .done file when complete. The requesting process only has to see the .done file via an ftp ls to know the results file it refers to is complete.
    __________________________________________________________________________________

    ^M Free your mind!