我有一个执行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()。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top