どのように私はPerlは子プロセスを待つことができますが、システムとバックグラウンドで起動しましたか()?
-
06-09-2019 - |
質問
私は簡単にするために、複数のパラメータのためのシェルスクリプトを実行し、いくつかのPerlコードを持って、私はちょうど私がこのようなコードを持っていると仮定します。
for $p (@a){
system("/path/to/file.sh $p&");
}
私はその後、いくつかのより多くの事をしたいと思いますが、私はすべての子プロセスを続行する前に終了するのを待つための方法を見つけることができません。
)(フォークを使用するようにコードを変換することは困難です。もっと簡単な方法はありませんか?
解決
フォーク/ 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";
他のヒント
あなたが何かを変更する必要があるとしている、フォークを使用するようにコードを変更することは、おそらく簡単ですが、あなたはフォークを使用してに対して死んで設定されている場合、あなたはそれが行われたときに、ファイルに触れるラッパーシェルスクリプトを使用して、持っている可能性がありファイルの存在のために、あなたの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はスクリプトが待つために何を知っていないことを意味する、かもしれないものは考えていないことを意味します。
あなたはPerlスクリプトまでのPIDを通信するために試みることができるが、それはすぐに手に負えなくなります。フォーク()を使用します。