【发布时间】:2011-01-09 04:29:09
【问题描述】:
谁能告诉我如何在 Perl 中触发后忘记一个进程?我已经看过 ruby: how to fire and forget a subprocess? 在 Ruby 中做同样的事情。
【问题讨论】:
标签: perl process fire-and-forget
谁能告诉我如何在 Perl 中触发后忘记一个进程?我已经看过 ruby: how to fire and forget a subprocess? 在 Ruby 中做同样的事情。
【问题讨论】:
标签: perl process fire-and-forget
来自perlfaq8对How do I start a process in the background?的回复
几个模块可以启动不会阻塞您的 Perl 的其他进程 程序。您可以使用 IPC::Open3、Parallel::Jobs、IPC::Run 和一些 POE 模块。有关详细信息,请参阅 CPAN。
你也可以使用
system("cmd &")
或者您可以使用 perlfunc 中“fork”中记录的 fork,进一步 perlipc 中的示例。如果您使用的是 Unix,请注意一些事项- 喜欢系统:
STDIN、STDOUT 和 STDERR 是共享的
主进程和后台进程(“子进程” 进程)共享相同的 STDIN、STDOUT 和 STDERR 文件句柄。如果 两者都尝试立即访问它们,可能会发生奇怪的事情。你 可能想为孩子关闭或重新打开这些。你可以得到 通过“打开”管道来解决这个问题(参见 perlfunc 中的“打开”),但在 在某些系统中,这意味着子进程不能活得比 父母。
信号
你必须捕捉到 SIGCHLD 信号,可能还有 SIGPIPE。 当后台进程完成时发送 SIGCHLD。 SIGPIPE 是 当您写入其子进程已关闭的文件句柄时发送 (未捕获的 SIGPIPE 可能会导致您的程序静默死亡)。 这不是 "system("cmd&")" 的问题。
僵尸
你必须准备好“收割”子进程,当它 完成。
$SIG{CHLD} = sub { wait };
$SIG{CHLD} = 'IGNORE';
您也可以使用双叉。您立即 wait() 等待您的 第一个孩子,初始化守护进程将为您的孙子等待() 一旦退出。
unless ($pid = fork) {
unless (fork) {
exec "what you really wanna do";
die "exec failed!";
}
exit 0;
}
waitpid($pid, 0);
有关执行此操作的其他代码示例,请参阅 perlipc 中的“信号”。 僵尸不是"system("prog &")"的问题。
【讨论】:
如果你想守护你的 Perl 脚本,我会查看 Proc::Daemon.
【讨论】:
你不应该使用system(),因为我知道这个调用会在继续执行之前等待函数的返回。我会简单地使用 linux 并以这种方式启动该过程,但请记住,这种方式会引发 shell 的新副本,因此如果您正在寻找性能,我不会在循环中执行此操作:
process_name > /dev/null 2>&1 &;
这将启动将STDOUT 和STDERR 重定向到/dev/null 的过程。
【讨论】:
如果您希望“父”进程退出时看门狗“子”进程消失,那么您并不真正希望父进程“触发并忘记”子进程。您要么需要 fork(如 brian d foy 所述),要么将父级的 PID 传递给子级(以便后者可以轮询进程表 - 不推荐)。
【讨论】: