我怎样才能使Perl的等待子进程在系统后台启动()?
-
06-09-2019 - |
题
我有一个执行shell脚本的多个参数,以简化一些Perl代码,我就认为我有代码看起来像这样的:
for $p (@a){
system("/path/to/file.sh $p&");
}
我想以后做一些更多的东西,但我不能找到一种方法来等待所有的子进程在继续之前完成。
转换的代码使用fork()是困难的。是不是有一个更简单的方法?
解决方案
使用叉/ EXEC /等待是不那么差:
my @a = (1, 2, 3);
for my $p (@a) {
my $pid = fork();
if ($pid == -1) {
die;
} elsif ($pid == 0) {
exec '/bin/sleep', $p or die;
}
}
while (wait() != -1) {}
print "Done\n";
其他提示
您将不得不改变一些东西,换用叉的代码可能是简单的,但如果你是坚决反对使用叉子,你可以使用触摸当它完成,然后有一个文件的包装shell脚本你的Perl代码检查该文件是否存在。
下面是包装器:
#!/bin/bash
$*
touch /tmp/$2.$PPID
您的Perl代码看起来像:
for my $p (@a){
system("/path/to/wrapper.sh /path/to/file.sh $p &");
}
while (@a) {
delete $a[0] if -f "/tmp/$a[0].$$";
}
但我认为分岔代码是更安全和更清楚:
my @pids;
for my $p (@a) {
die "could not fork" unless defined(my $pid = fork);\
unless ($pid) { #child execs
exec "/path/to/file.sh", $p;
die "exec of file.sh failed";
}
push @pids, $pid; #parent stores children's pids
}
#wait for all children to finish
for my $pid (@pids) {
waitpid $pid, 0;
}
转换为叉()可能是困难的,但它是正确的工具。系统()是一个阻塞呼叫;你被执行外壳并告诉它在后台运行脚本获得非阻塞行为。这意味着,Perl有不知道孩子的PID可能是,这意味着你的脚本不知道要等到什么。
您可以尝试到了沟通的PID的Perl脚本,但迅速失控。使用fork()。
不隶属于 StackOverflow