Yes, your backgrounded process should complete even if the script exits first.
The system call forks, what means that at that point a new, independent, process is created as a near clone of the parent. That process is then replaced by the command to run, or by a shell that will run the command.† The system
then wait
s for the child process to complete.
The &
in the command makes sure that it is a shell that is run by the system
, which then executes the command. The shell itself fork
s a process (subshell), in which the command is executed, and doesn't wait for it but returns right away.
At that point system
's job is done and it returns control to the script.
The fate of the process forked by the shell has nothing more to do with the shell, or with your script, and the process will run to its completion.
The parent may well exit right away. See this with
use warnings;
use strict;
use feature 'say';
system("(sleep 5; echo hi) &");
say "Parent exiting.";
or, from a terminal
perl -wE'system("(sleep 3; echo me)&"); say "done"'
Once in the shell, the ()
starts a sub-shell, used here to put multiple commands in the background for this example (and representing your command). Keep that in mind when tracking process IDs via bash
internal variables $BASHPID
, $$
, $PPID
(here $$
differs from $BASHPID
)
perl -wE'say $$; system("
( sleep 30; echo \$BASHPID; echo \$PPID; echo \$\$ ) &
"); say "done"'
Then view processes while this sleeps (by ps aux
on my system, with | tail -n 10
).
Most of the time the PID of a system
-run command will be by two greater than that of the script, as there is a shell between them (for a backgrounded process as well, on my system). In the example above it should be greater by 3, because of an additional ()
subshell with mulitple commands.
This assumes that the /bin/sh
which system
uses does get relegated to bash
.
Note: when the parent exits first the child is re-parented by init
and all is well (no zombies).
† From system
Does exactly the same thing as exec
, except that a fork is done first and the parent process waits for the child process to exit. Note that argument processing varies depending on the number of arguments. If there is more than one argument in LIST, or if LIST is an array with more than one value, starts the program given by the first element of the list with arguments given by the rest of the list. If there is only one scalar argument, the argument is checked for shell metacharacters, and if there are any, the entire argument is passed to the system's command shell for parsing (this is /bin/sh -c
on Unix platforms, but varies on other platforms). If there are no shell metacharacters in the argument, it is split into words and passed directly to execvp
, which is more efficient. ...
The "... starts the program given by the first element ..." also means by execvp
, see exec.