3

我正在尝试在 PHP CLI 脚本中调用一个长时间运行的 shell 命令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');,则在睡眠结束之前我不会到达我的信号处理程序。我有两个问题:

  1. 如何获得信号以使用exec(或shell_execproc_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_openand proc_terminate

于 2012-04-24T07:46:21.513 回答