【问题标题】:How can I fire and forget a process in Perl?如何在 Perl 中触发并忘记一个进程?
【发布时间】:2011-01-09 04:29:09
【问题描述】:

谁能告诉我如何在 Perl 中触发后忘记一个进程?我已经看过 ruby: how to fire and forget a subprocess? 在 Ruby 中做同样的事情。

【问题讨论】:

    标签: perl process fire-and-forget


    【解决方案1】:

    来自perlfaq8How 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 &")"的问题。

    【讨论】:

    • 非常感谢,没想到在命令中使用后台shell操作符。那成功了。不幸的是,我无法使用其他的,因为我正在开发一个几乎没有模块的严重受限的系统。
    • 嗯,没错,如果你发出带有 '&' 字符的 system() 命令,它会立即返回,因此我建议的反引号运算符方法不太好 - 最好使用 Perl系统调用,而不是调用一个全新的 shell 副本。
    【解决方案2】:

    如果你想守护你的 Perl 脚本,我会查看 Proc::Daemon.

    【讨论】:

    • 实际上,我不想守护它,我只需要在执行我的主脚本期间在后台启动一个看门狗脚本。而且我只有基本的 Perl 5.6.0 可以使用,因为这是在内存严重受限的嵌入式系统上执行的,而且我几乎没有可以使用的模块。
    【解决方案3】:

    你不应该使用system(),因为我知道这个调用会在继续执行之前等待函数的返回。我会简单地使用 linux 并以这种方式启动该过程,但请记住,这种方式会引发 shell 的新副本,因此如果您正在寻找性能,我不会在循环中执行此操作:

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

    这将启动将STDOUTSTDERR 重定向到/dev/null 的过程。

    【讨论】:

      【解决方案4】:

      如果您希望“父”进程退出时看门狗“子”进程消失,那么您并不真正希望父进程“触发并忘记”子进程。您要么需要 fork(如 brian d foy 所述),要么将父级的 PID 传递给子级(以便后者可以轮询进程表 - 不推荐)。

      【讨论】:

      • 实际上,将看门狗脚本作为子进程运行可能是个坏主意,因为如果主脚本意外死掉,看门狗应该做点什么(但如果父进程死了,那么它的所有子进程也会死掉) )。另一种方法是让“主进程”设置一个命名管道并向其写入“心跳”消息+退出时的“完成”消息,而看门狗(通过系统以真正的“即发即弃”模式启动( "cmd &")) 从命名管道中读取数据,并在“完成”消息到达或“心跳”消息停止到达时发出通知。
      猜你喜欢
      • 2010-10-22
      • 2017-11-30
      • 2022-01-22
      • 1970-01-01
      • 1970-01-01
      • 2023-03-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多