1

通常は終了するまで実行されるプログラムがありますが、状況によっては、2 つの子プロセスが作成され、メイン プロセスが終了します。メインプロセスが終了した後も、子プロセスは引き続き実行されます。

このプログラムを PHP で呼び出したい。

もともと、私は次の戦略を使用しました(有効なphpコードではありません)、

$process=proc_open("python xxx.py");
while (1) {
   sleep(5);
   $status = proc_get_status($process);
   if (!$status['running']) {
       exit_loop;
   }
   if (timeout) {
      proc_terminate($process, 9);
      exit_loop;
   }
}

しかし、すぐに、$status['running'] が false であるというプロセスが実際にはすぐに終了するというバグが見つかりましたが、子プロセスはまだ実行されています。すべての子プロセスを実際に待つ方法は?

2 番目の質問は、proc_terminate を調べていないことですが、proc_terminate が期待どおりに機能しない可能性があることも確認しました。$process は bash ですが、実際の python プロセスではないためですか? また、終了したのは親のメインプロセスのみであり、子プロセスではないためかもしれません。

上記のコードが堅牢な PHP コードであるかどうかについて、誰かがアドバイスしてくれますか? これに対処するより良い方法はありますか?

ありがとう。

======================

より詳しい情報、

  1. このプログラムはシェル (CLI) で実行しますが、CGI 関数とは関係ありません。したがって、max_execution_time について心配する必要はありません。

  2. proc_open によって開かれたメイン プロセスによって作成された子プロセスを待ちたいので、プログラム内にプロセスを 1 つだけ作成します。

  3. 呼び出したい python プログラムが長時間ハングする可能性があるため、タイムアウトを確認して終了したいと考えています。

4

3 に答える 3

2

proc_get_statusは子プロセスのpidを取得できます

$status = proc_get_status($process);
$pid = $status["pid"]

pcntl_waitpid次に、子プロセスが終了するまで待機するために使用できます

pcntl_waitpid($pid, $child_status);

pcntlただし、phpを拡張子付きでコンパイルする必要があります。

PCNTL関数を参照してください

更新:タイムアウト後に子プロセスを強制終了する場合

まずSIGALARM、メインプロセスにハンドラーをインストールします

function term_proc() {
   // terminate your all child process
}

pcntl_signal(SIGALARM, term_proc);

2番目:pcntl_alarm数秒後にアラーム信号を送信するために使用します

pcntl_alarm($seconds)

2番目の質問については、proc_terminateどのプロセスを開いても機能します。

于 2011-12-08T01:29:54.800 に答える
2

生成されたプロセスとなんらかの方法でやり取りするつもりがない場合 (たとえば、その入力または出力をリダイレクトするなど)、system代わりに を使用できますproc_opensystem生成されたプロセスが終了するまで待機するため、頻繁にチェックする必要はありません。

注意:別のプロセスを待機すると、max_execution_time. また、Web サーバーの実行ユニットの内部管理とうまく機能しない場合もあります。

更新:プロセス X を起動し、プロセス X 自体が起動するすべてのプロセスが終了するのを待ってから続行したいようです。悪い知らせを伝えて申し訳ありませんが、PHP はこの種の作業を意図したものではありません。また、標準の PHP では目的を達成することはできません。この機能を公開するカスタム拡張機能を C で作成することは確かに可能ですが、私の知る限り、公開されているような拡張機能はありません。

于 2011-12-08T01:18:59.273 に答える
2

親プロセスがすべての子孫をたどることは困難です。プロセスは、子供の直接の死亡のみを通知されます。必要なことを実行できるいくつかの異なるメカニズムがありますが、プロセスの孫を気にしないようにアプリケーションを書き直すのが最善です。

  • cgroupssystemd単一の初期execve(2)呼び出しから開始されたすべての子プロセスを追跡するのに十分なメカニズムを提供します。

    自分で使用することはできますが、他のツールが同様のことを行っているときにプロセス管理cgroupsに使用しようとした場合の結果についてはあまり学んでいません。(それは私の限界以上の無知です-おそらくそれはそれを美しく処理します.私は夢を見るのが好きです。)cgroupssystemdlibvirtcgroups

  • プロセスでaを開き、 「誤って」使用されないように十分に高いファイル記述子で、子プロセスに作成されたpipe(2)の読み取り終了を与えます。pipe(7)(dup2(fd[0], 20)おそらく良いでしょう。)他のプログラムが予期しないファイル記述子を閉じていないことを確認してください。のコマンドを使用して、書き込み終了 ( )のO_NONBLOCKフラグを設定します。fd[1]fcntl(2)F_SETFL

    定期的にパイプにバイトを書き込もうとします。最終的に、読み取り側がすべての子によって閉じられたことを示すエラーが返されるか、パイプがいっぱいでまだ子が実行されていることを意味するset toEPIPEのエラーが返されます。errnoEAGAIN

于 2011-12-08T01:40:50.547 に答える