2009-05-26 21 views
10

私は単純化するために、複数のパラメータのためのシェルスクリプトを実行し、いくつかのPerlコードを、持っている、私はちょうど私がこのようなコードを持っていると仮定します:system()でバックグラウンドで起動した子プロセスのためにPerlが待機するようにするにはどうすればよいですか?

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

私は後にいくつかのより多くの事をしたいと思いますしかし、私はすべての子プロセスが完了するのを待ってから続行する方法を見つけることができません。

fork()を使用するようにコードを変換するのは難しいでしょう。簡単な方法はありませんか?

+0

file.shの実際のリターンコードが必要ですか?完了したらファイルに書き込むようにスクリプトを変更できますか? – mkb

+1

なぜコードをフォークに変換するのが難しいのですか?サブルーチンのすべての詳細を非表示にします。 system()を再定義して、新しいサブルーチンを呼び出すことさえできます。 –

+0

私はたぶんこの部分を分岐して別のスクリプトに分割し、それをシステムコールから呼び出します。 –

答えて

16

/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"; 
+1

失敗したフォークをチェックしておらず、ベアワードpidを$ pidではなく@pidsにプッシュしています。 exitがおそらくdieでなければならず、execが失敗したことを意味します。 –

+0

固定。ありがとう、私は本当にPerlのネイティブスピーカーではありません。 – Dave

+0

$ pid == -1はおそらく!defined($ pid)でなければなりません。 –

8

fork()に変換するのは難しいかもしれませんが、正しいツールです。 system()はブロッキング呼び出しです。シェルを実行し、スクリプトをバックグラウンドで実行するように指示することによって、非ブロック動作を得ています。つまり、Perlは子供のPIDが何であるか分からず、あなたのスクリプトは何を待つべきかを知らないということです。

PIDをPerlスクリプトまで通信しようとすることはできますが、それはすぐに手を抜くことになります。 fork()を使用します。

13

フォークを使用するようにコードを変更するのはおそらく簡単ですが、フォークを使用して死んだ場合は、ファイルが終了してからそれに触れるラッパーシェルスクリプトを使用できますあなたの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; 
} 
+0

これははるかに良い答えです。 – zdim

+0

明らかにこれを行うと、ゾンビプロセスがたくさん作成されます。 https://en.wikipedia.org/wiki/Zombie_process –

+1

@PratyushRathoreそうはいけません。ゾンビは、親プロセスがwaitまたはwaitpidを呼び出さない場合に発生します。あなたが見ることができるように、親は終了した子供のためにwaitpidを呼び出しています。あなたがゾンビの束を取得している場合、あなたは何か間違っているか、最初の子供のうちの1人が長い時間をとり、後の子供たちが出てきました(しかし、刈り取られていません)。あなたは 'while(waitpid(-1、WNOHANG)> 0){sleep 1}'に切り替えて、次の終了した子を獲得することができます。 –

関連する問題