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

Hi, I'm relatively new to perl programming, and I couldn't find an answer to this on perldoc (maybe I didn't know what to search for). I need to invoke a long-running shell script from a perl script, and the perl script needs to know the shell script's PID so that it can send it signals later. The shell script does a bunch of stuff and then sits in a sleep loop waiting for signals from the perl script.

I would like to execute the shell script as an independent process (i.e. fork then exec), and I don't want the perl script to wait for the shell script to exit before continuing, because it never will (until the perl script sends the right signal). As far as I can tell, the system() function doesn't do the right thing (waits for child to exit), neither does exec() (never returns), and I don't think qx/backticks would work either for the same reason as with system().

Assuming I can execute a shell script "in the background" and continue execution, I then need to get the PID of the child process. How do I do that? I know perl reserves $$ for the PID of the perl script and offers a getppid() function to get the parent PID, but how do I get the child PID?

In case I'm not being clear, this is what I want to do in shell syntax:

my_script.sh & pid=$!

Of course, $! means something completely different in perl. I'm sure this is a not-so-uncommon programming task, so how do I do it?

Replies are listed 'Best First'.
Re: start process in bg, get child PID
by Sidhekin (Priest) on Jul 17, 2006 at 22:45 UTC

    fork returns the PID of the child process in the parent (and 0 to the child process), so if I read you right, this ought to do it:

    my $pid = fork or exec @whatever;

    Update: In light of the other reply ... if you want to check that the fork succeeded, you need to check for definedness, not truth:

    defined(my $pid = fork) or die "No fork: '$!'"; if ($pid==0) { # child exec @whatever or die "No exec: '$!'"; } # parent

    print "Just another Perl ${\(trickster and hacker)},"
    The Sidhekin proves Sidhe did it!

Re: start process in bg, get child PID
by Hue-Bond (Priest) on Jul 17, 2006 at 22:47 UTC
    As far as I can tell, the system() function doesn't do the right thing (waits for child to exit), neither does exec() (never returns), and I don't think qx/backticks would work either for the same reason as with system().

    Oddly, although you know you want fork and exec, it isn't in this list of possible alternatives. You will be glad to know that fork gives the child PID to the parent process. Very roughly, that could be:

    defined (my $pid = fork) or die "fork: $!"; if ($pid) { ## child exec '/bin/sh' or die "exec: $!"; } ## parent sleep 10; kill 2, $pid;

    Update: Fixed a nasty fork or die. Thanks to Sidhekin

    --
    David Serrano