我不确定这个问题是否特定于Perl,但它是我正在使用的语言。假设我启动后台进程以将网页保存到本地文件,如下所示:
system("curl http://google.com > output_file.html &");
我知道这会启动一个后台进程,虽然我不完全确定细节(例如它是否有自己的PID?)。但对我来说特别重要的是,如果启动它的进程在curl完成下载之前终止会发生什么?卷曲是允许继续,还是会终止?
是否有任何理由解决方案不会在nohup
(nohup curl ...
)之前添加上述命令?见http://linux.101hacks.com/unix/nohup-command/
答案 0 :(得分:3)
是的,即使脚本首先退出,您的后台进程也应该完成。
system调用fork,这意味着在此时创建一个新的独立进程作为父进程的近似克隆。然后,该进程将由要运行的命令替换,或由将运行该命令的shell替换。† system
然后wait
用于子进程完成。< / p>
命令中的&
确保它是由system
运行的shell,然后执行命令。 shell本身fork
是一个进程(子shell),执行命令,不等待它,但立即返回。
此时system
的工作已完成,并将控制权返回给脚本。
shell分叉的进程的命运与shell或脚本无关,并且进程将运行完成。 父母可能会立即退出。请参阅
use warnings;
use strict;
use feature 'say';
system("(sleep 5; echo hi) &");
say "Parent exiting.";
或者,从终端
perl -wE'system("(sleep 3; echo me)&"); say "done"'
进入shell后,()
启动一个子shell,此处用于在此示例的后台放置多个命令(并表示您的命令)。通过bash
internal variables $BASHPID
,$$
,$PPID
(此处为$$
differs from $BASHPID
)
perl -wE'say $$; system("
( sleep 30; echo \$BASHPID; echo \$PPID; echo \$\$ ) &
"); say "done"'
然后在我的系统上通过ps aux
使用| tail -n 10
来查看进程。
大多数情况下,system
- 运行命令的PID将比脚本的PID大2,因为它们之间有一个shell(对于我的系统上的后台进程)。在上面的示例中,它应该大于3,因为带有多个命令的附加()
子shell。
这假定/bin/sh
使用的system
确实被降级为bash
。
注意:当父母退出时,孩子会被init
重新成为父母,一切都很好(没有僵尸)。
†来自system
与
exec
完全相同,除了首先完成fork并且父进程等待子进程退出。请注意,参数处理因参数的数量而异。如果LIST中有多个参数,或者LIST是具有多个值的数组,则使用列表其余部分给出的参数启动列表的第一个元素给出的程序。如果只有一个标量参数,则检查参数是否为shell元字符,如果有,则将整个参数传递给系统的命令shell进行解析(在Unix平台上为/bin/sh -c
,但在其他方面有所不同平台)。如果参数中没有shell元字符,则将其拆分为单词并直接传递给execvp
,这样效率更高。 ...
“ ...启动第一个元素给出的程序...... ”也意味着execvp
,见exec。