简体   繁体   English

如何在Perl中解雇一个进程?

[英]How can I fire and forget a process in Perl?

Can somebody please tell me how to fire-and-forget a process in Perl? 有人可以告诉我如何在Perl中解雇一个过程吗? I've already looked at ruby: how to fire and forget a subprocess? 我已经看过ruby:如何触发并忘记子流程? for doing the same in Ruby. 在Ruby中也是如此。

From perlfaq8 's answer to How do I start a process in the background? perlfaq8的答案到如何在后台启动进程?


Several modules can start other processes that do not block your Perl program. 几个模块可以启动其他不会阻止您的Perl程序的进程。 You can use IPC::Open3, Parallel::Jobs, IPC::Run, and some of the POE modules. 您可以使用IPC :: Open3,Parallel :: Jobs,IPC :: Run和某些POE模块。 See CPAN for more details. 有关更多详细信息,请参见CPAN。

You could also use 您也可以使用

system("cmd &")

or you could use fork as documented in "fork" in perlfunc, with further examples in perlipc. 或者您可以使用perlfunc的“ fork”中所述的fork,以及perlipc中的更多示例。 Some things to be aware of, if you're on a Unix- like system: 如果您使用的是类似Unix的系统,请注意以下几点:

STDIN, STDOUT, and STDERR are shared 共享STDIN,STDOUT和STDERR

Both the main process and the backgrounded one (the "child" process) share the same STDIN, STDOUT and STDERR filehandles. 主进程和后台进程(“子”进程)都共享相同的STDIN,STDOUT和STDERR文件句柄。 If both try to access them at once, strange things can happen. 如果两个都尝试一次访问它们,则可能会发生奇怪的事情。 You may want to close or reopen these for the child. 您可能要为孩子关闭或重新打开它们。 You can get around this with "open"ing a pipe (see "open" in perlfunc) but on some systems this means that the child process cannot outlive the parent. 您可以通过“打开”管道来解决此问题(请参阅perlfunc中的“ open”),但是在某些系统上,这意味着子进程无法超过父进程。

Signals 讯号

You'll have to catch the SIGCHLD signal, and possibly SIGPIPE too. 您必须捕获SIGCHLD信号,并且可能还捕获SIGPIPE。 SIGCHLD is sent when the backgrounded process finishes. 后台进程完成后,将发送SIGCHLD。 SIGPIPE is sent when you write to a filehandle whose child process has closed (an untrapped SIGPIPE can cause your program to silently die). 当您写入其子进程已关闭的文件句柄时,将发送SIGPIPE(未捕获的SIGPIPE可能导致您的程序无声地死掉)。 This is not an issue with "system("cmd&")". 这不是“ system(” cmd&“)”的问题。

Zombies 僵尸

You have to be prepared to "reap" the child process when it finishes. 您必须准备好在子进程完成后“收获”子进程。

   $SIG{CHLD} = sub { wait };

   $SIG{CHLD} = 'IGNORE';

You can also use a double fork. 您也可以使用双叉。 You immediately wait() for your first child, and the init daemon will wait() for your grandchild once it exits. 您可以立即等待()第一个孩子,并且init守护进程将在退出后为您的孙子等待()。

   unless ($pid = fork) {
       unless (fork) {
           exec "what you really wanna do";
           die "exec failed!";
       }
       exit 0;
   }
   waitpid($pid, 0);

See "Signals" in perlipc for other examples of code to do this. 有关执行此操作的其他代码示例,请参见perlipc中的“信号”。 Zombies are not an issue with "system("prog &")". 僵尸不是“ system(” prog&“)”的问题。

如果您想守护您的Perl脚本,我将研究Proc :: Daemon。

Well you shouldn't use system() as I understand this call will wait for the return of the function before continuing execution. 好吧,您不应该使用system()因为据我了解,此调用将等待函数返回,然后再继续执行。 I would simply shell out to linux and start the process that way, though keep in mind this way will envoke a new copy of the shell and so if you're looking for performance I wouldnt do this in a loop for example: 我会简单地将Linux外壳化,然后以这种方式启动该过程,尽管请记住,这种方式将调用外壳的新副本,因此,如果您要寻找性能,我就不会在循环中这样做,例如:

process_name > /dev/null 2>&1 & ; process_name > /dev/null 2>&1 & ;

That will start the process redirecting STDOUT and STDERR to /dev/null . 这将开始将STDOUTSTDERR重定向到/ dev / null的过程

If you want the watchdog "child" process to go away when the "parent" process exits then you don't really want the parent process to "fire and forget" the child process. 如果您希望看门狗的“子”进程在“父”进程退出时消失,那么您实际上并不希望父进程“解雇”子进程。 You either need to fork (as described by brian d foy) or pass the PID of the parent to the child (so the latter can poll the process table - not recommended). 您要么需要进行分叉(如brian d foy所述),要么将父级的PID传递给子级(以便后者可以轮询进程表-不推荐)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM