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

I'm in the middle of a short script that's sole purpose is to launch a program using system() (lets call it program_a), run through a loop, and then kill the program_a it started up.

The problem is, it will not be the only instance of the Program_A running, so I need to catch the pid assigned to it on launch.

Is there a way to do this?

i tried $pid = system($command); but that was a no go.

Replies are listed 'Best First'.
Re: catching a pid
by rjray (Chaplain) on Mar 22, 2002 at 01:28 UTC

    You don't want to use system for something like this. Instead, you need to use fork followed by exec. The system function doesn't run in an asynchronous mode, for one thing. You would have to append a "&" to the command line to get it to background. Additionally, you couldn't just wait for a child process to exit, because the immediate child of you process is a shell, probably /bin/sh, used to execute the requested command.

    There are numerous nodes out there that cover this topic, so I'll leave the finding of more specific code examples as an exercise. Start with the link above, to understand fork better, and go forward from there.

    --rjray

Re: catching a pid
by graff (Chancellor) on Mar 22, 2002 at 06:09 UTC
    You didn't say what sort of OS your working with, or what sort of process "program_a" is... Did you look into something like this:
    open( PROC, "| program_a" ); sleep $n; close PROC;
    Or maybe program_a isn't a pipeline sort of process -- you could try something like the following -- note that
    open( PROC, "| command" )
    returns the process-id of the command that is launched. It's not pretty, and not portable outside of *n*x, but it worked for me (maybe you need better time resolution on the wait; if so, good luck):
    $spid = open( SH, "| /bin/sh" ); select SH; $|++; print "program_a &\n"; $slept = 0; until ( $ps =~ m{\b$spid\s+$$\s+/bin/sh\b} && $ps =~ m{\b\d+\s+$spid\s+program_a\b} ) { sleep 1; $slept++; $ps = `/bin/ps -o pid -o ppid -o comm`; } if ($ps =~ m{\b(\d+)\s+$spid\s+sleep\s}) { $cpid = $1; sleep ($n-$slept) if ( $n>$slept ); print SH "kill -9 $cpid\n"; } else { print "Damn! Lost the kid.\n"; } close SH;
    If I put parens around the target pid in the "until ()" match, $1 shows up empty outside that block, so I have to do the match again.