我怎样才能让Perl等待在system()后台启动的subprocess?

我有一些执行多个参数的shell脚本的Perl代码,为了简化,我假设我有这样的代码:

for $p (@a){ system("/path/to/file.sh $p&"); } 

之后我想做更多的事情,但是我无法find一种方法来等待所有的subprocess完成,然后再继续。

转换代码使用fork()将是困难的。 有没有更简单的方法?

Solutions Collecting From Web of "我怎样才能让Perl等待在system()后台启动的subprocess?"

使用fork / exec / wait并不是那么糟糕:

 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"; 

你将不得不改变一些东西,改变代码来使用fork可能更简单,但是如果你使用fork的时候,你可以使用一个wrapper 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; } 

转换为fork()可能很困难,但它是正确的工具。 system()是一个阻塞调用; 你通过执行一个shell并告诉它在后台运行脚本来获得非阻塞行为。 这意味着Perl不知道孩子的PID可能是什么,这意味着你的脚本不知道该等什么。

您可以尝试将PID传递给Perl脚本,但这很快就失控了。 使用fork()。