3

PHPCLIスクリプト内で。を使用して長時間実行されるシェルコマンドを呼び出そうとしていますexec()。しかし、PHPスクリプトを中断して、生成された子プロセスを強制終了する方法を一生理解することはできません。を呼び出すとすぐにexec()、シグナルハンドラが無視されるようです。次のコードは、私が期待するとおりに機能します。SIGTERMをプロセスに送信すると、エコーSIGTERMしてすぐに終了します。

<?php
  declare(ticks = 1);

  function sig_handler($signo) {
    switch ($signo) {
      case SIGTERM:
        echo 'SIGTERM' . PHP_EOL;
        flush();
        break;
      default:
    }
  }

  pcntl_signal(SIGTERM, 'sig_handler', false);

  sleep(60);
?>

ただし、に置き換えるsleep(60);exec('sleep 60');、スリープが終了するまでシグナルハンドラに到達しません。2つの質問があります:

  1. execシグナルを(またはshell_execまたは)で動作させるにはどうすればよいproc_openですか?
  2. シグナルをトラップしたときに、によって生成された子プロセスをどのように強制終了できexecますか?
4

1 に答える 1

5

ドキュメントには次のように書かれています。

プログラムがこの関数で開始された場合、プログラムがバックグラウンドで実行を継続するには、プログラムの出力をファイルまたは別の出力ストリームにリダイレクトする必要があります。そうしないと、プログラムの実行が終了するまでPHPがハングします。

(エンファシスマイン。)ハンギングはシグナルハンドラーにも当てはまると思います。

子プロセスを制御できるようにするには、fork+execを使用して昔ながらの方法で子プロセスを実行する必要があるように見えます。

switch ($pid = pcntl_fork()) {
  case -1: // failed to create process
     die('Fork failed');
  case 0: // child
     pcntl_exec($path,$args);
     die('Exec failed');
}

親プロセスが子のプロセスIDをに$pid持つと、SIGINTを子に送信できますposix_kill($pid, SIGINT)

更新:どうやらあなたも使用することができますproc_openproc_terminate

于 2012-04-24T07:46:21.513 に答える