Jas*_*nes 8 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->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";
Run Code Online (Sandbox Code Playgroud)
我也试过了
while (1) {
$p = kill 0, $p;
print "x";
sleep 1 if $p;
print "*";
last unless $p;
}
Run Code Online (Sandbox Code Playgroud)
但print
由于某种原因它甚至没有达到第一,并且永远不会退出.
该wait
系列函数只有在子进程的工作,甚至waitpid
.睡眠过程不是你的孩子,而是你孩子的孩子.这是因为system
基本上是fork
+ exec
.通过使用Parallel :: ForkManager +系统,你正在分叉,然后再次分叉,然后执行睡眠.
既然你已经分叉了,你应该使用exec.这有一个额外的好处,就是不需要调用pgrep和它的计时问题(即,在子进程执行系统之前,父进程可能会调用pgrep).
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);
Run Code Online (Sandbox Code Playgroud)
为简单起见,它现在正在使用睡眠.必须抑制Perl警告"不可能达到声明",因为Perl没有意识到$pm->start
已经分叉了.这应该是,no warnings "exec"
但这不起作用所以我不得不压制它们.