当前位置:  开发笔记 > 编程语言 > 正文

为什么我从Perl的system()开始是一个子进程?

如何解决《为什么我从Perl的system()开始是一个子进程?》经验,为你挑选了4个好方法。

Perl的system()启动一个进程,但打破了父/子关系?

test.pl:

use POSIX;

system("./test.sh &");

my $pid = `ps -C test.sh -o pid=`;

print "pid: -$pid-\n";

waitpid($pid, 0);

test.sh:

while true
do
    sleep 1
done

当我运行test.pl时,它会找到并打印一个正确的test.sh. 但是waitpid()返回-1并且test.pl退出.test.pl存在后,test.sh仍在运行.

看起来test.sh不是test.pl的子代,它会破坏waitpid().为什么会发生这种情况以及如何使system()表现出来?这是因为Perl会自动清除孩子吗?如果是,我该如何解决明确等待儿童的一般任务?

更新:

下面的答案建议使用fork/exec.最初的问题是:

    从Perl脚本,运行启动服务的命令行实用程序.该实用程序退出但服务仍然存在.

    过了一段时间,找到服务的pid并等待它.

虽然它解决了这个问题,但fork/exec并没有解决这个问题.



1> Liudvikas Bu..:

test.sh进程不是您的子进程.该system()分叉外壳(这是你的孩子),壳牌分叉运行该程序test.sh一个孩子.你孩子的外壳退出了.



2> Leon Timmerm..:

你可能想做的是这样的:

my $pid = fork || exec './test.sh';
print "pid: -$pid-\n";
waitpid($pid, 0);

虽然由于shell脚本处于无限循环中,但它将永远等待.



3> jrockway..:

通常,如果您不希望Perl帮助您,您应该手动fork和exec.很难确切地确定你在做什么,但我认为你想要这个:

my $pid = fork;
unless($pid){
    # child;
    exec(qw/sh test.sh/);
}

# parent
...
waitpid $pid, 0;

就个人而言,我更愿意让AnyEvent照看孩子:

my $done = AnyEvent->condvar;

my $pid = fork;

unless( $pid ) { ... }

my $w = AnyEvent->child (
   pid => $pid,
   cb  => sub {
      my ($pid, $status) = @_;
      warn "pid $pid exited with status $status";
      $done->send;
   },
);

$done->recv; # control resumes here when child exits

或者,更一般地说:http://github.com/jrockway/anyevent-subprocess/tree/master



4> aks..:

为了进一步解释Liudvikas的回答 -

system("./test.sh &")
 |
 |--> (P) /bin/sh (to run test.sh)
       |
       |--> (P) test.sh & (still running)

(P) - process

在fork'ing并运行test.sh脚本后,/ bin/sh shell(它是Perl系统调用的子代)退出,因此从waitpid()获得-1返回值.

推荐阅读
LEEstarmmmmm
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有