Linux 为什么';是否等待进程退出?

Linux 为什么';是否等待进程退出?,linux,perl,waitpid,Linux,Perl,Waitpid,在下面的脚本中,我试图弄清楚waitpid是如何工作的,但它不会等待ssh进程退出done立即打印,而不是在ssh过程存在之后打印 问题 如何使waitpid仅在给定的pid退出时继续 #!/usr/bin/perl use strict; use warnings; use Parallel::ForkManager; use POSIX ":sys_wait_h"; my $pm = Parallel::ForkManager->new(5); my $pid = $pm->s

在下面的脚本中,我试图弄清楚
waitpid
是如何工作的,但它不会等待
ssh
进程退出
done
立即打印,而不是在
ssh
过程存在之后打印

问题

如何使
waitpid
仅在给定的pid退出时继续

#!/usr/bin/perl
use strict;
use warnings;
use Parallel::ForkManager;
use POSIX ":sys_wait_h";

my $pm = Parallel::ForkManager->new(5);
my $pid = $pm->start;
my $p = $pid;
if (!$pid) {
    system("ssh 10.10.47.47 sleep 10");
    $pm->finish;
}

$p = qx(/usr/bin/pgrep -P $p);
print "ssh pid is $p\n";

my $kid;
do {
    $kid = waitpid($p, 0);
} while $kid > 0;

print "done\n";
我也试过了

while (1) {
    $p = kill 0, $p;
    print "x";
    sleep 1 if $p;
    print "*";
    last unless $p;
}

但是由于某种原因,它甚至没有到达第一个
打印
,并且永远不会退出。

等待函数族只在子进程上工作,甚至
等待PID
。睡眠过程不是你的孩子,而是你孩子的孩子。这是因为
system
本质上是
fork
+
exec
。通过使用Parallel::ForkManager+系统,您正在分叉,然后再次分叉,然后执行sleep

既然您已经使用了fork,那么应该使用exec。这有一个额外的优点,即不需要调用pgrep,并且它存在计时问题(即,在孩子执行系统之前,家长可能会调用pgrep)

为了简单起见,它现在使用睡眠。来自Perl的警告“语句不太可能到达”必须被抑制,因为Perl没有意识到
$pm->start
已经分叉。这应该是
没有警告的“exec”
,但这不起作用,所以我不得不抑制它们

my $pm = Parallel::ForkManager->new(5);
my $pid = $pm->start;
my $p = $pid;
if (!$pid) {
    no warnings;  # no warnings "exec" is not working
    exec("sleep 10");
    $pm->finish;
}

print "sleep pid is $p\n";
waitpid($p, 0);