4

Perl の system() はプロセスを開始しますが、親子関係を壊しますか?

test.pl:

use POSIX;

system("./test.sh &");

my $pid = `ps -C test.sh -o pid=`;

print "pid: -$pid-\n";

waitpid($pid, 0);

test.sh:

while true
do
    sleep 1
done

test.pl を実行すると、test.sh の正しい pid が検出され、出力されます。しかし、waitpid() は -1 を返し、test.pl は終了します。test.pl が存在した後、test.sh はまだ実行されています。

test.sh は test.pl の子ではないようで、waitpid() が壊れます。なぜこれが起こるのか、system() を動作させる方法は? これは、Perl が子を自動的にクリアするためですか? はいの場合、子供を明示的に待機する一般的なタスクをどのように解決できますか?

アップデート:

以下の回答では、fork/exec の使用を提案しています。最初の問題はこれです:

  1. Perl スクリプトから、サービスを開始するコマンドライン ユーティリティを実行します。ユーティリティは終了しますが、サービスは残ります。

  2. しばらくしてから、そのサービスの pid を見つけて待機します。

fork/exec はこれを解決しませんが、問題は解決します。

4

4 に答える 4

16

test.sh プロセスは子プロセスではありません。system()シェル (あなたの子) をフォークし、そのシェルが test.sh プログラムを実行する子をフォークしました。あなたの子だったシェルが終了しました。

于 2009-02-17T15:17:35.583 に答える
6

おそらくやりたいことは次のようなものです。

my $pid = fork || exec './test.sh';
print "pid: -$pid-\n";
waitpid($pid, 0);

シェルスクリプトは無限ループにあるため、永久に待機します。

于 2009-02-17T15:23:26.117 に答える
6

一般に、Perlに助けてもらいたくない場合は、手動でフォークして実行する必要があります。あなたが何をしているのかを正確に判断するのは難しいですが、私はあなたがこれを望んでいると思います:

my $pid = fork;
unless($pid){
    # child;
    exec(qw/sh test.sh/);
}

# parent
...
waitpid $pid, 0;

個人的には、AnyEventにベビーシッターをさせることを好みます。

my $done = AnyEvent->condvar;

my $pid = fork;

unless( $pid ) { ... }

my $w = AnyEvent->child (
   pid => $pid,
   cb  => sub {
      my ($pid, $status) = @_;
      warn "pid $pid exited with status $status";
      $done->send;
   },
);

$done->recv; # control resumes here when child exits

または、より一般的には:http: //github.com/jrockway/anyevent-subprocess/tree/master

于 2009-02-17T15:23:55.960 に答える