php - 如何中断exec并杀死子进程

标签 php signals exec pcntl

我正在尝试使用 exec() 在 PHP CLI 脚本中调用长时间运行的 shell 命令。但我终其一生都无法弄清楚如何中断 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');,在 sleep 结束之前我不会到达我的信号处理程序。我有两个问题:

  1. 如何获取信号以使用 exec(或 shell_execproc_open)?
  2. 捕获信号后,如何终止 exec 产生的任何子进程?

最佳答案

documentation确实是这样说的:

If a program is started with this function, in order for it to continue running in the background, the output of the program must be redirected to a file or another output stream. Failing to do so will cause PHP to hang until the execution of the program ends.

(强调我的。)我想挂起也适用于信号处理程序。

为了能够控制子进程,看起来您必须以老式的方式执行它们,使用 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');
}

一旦父进程在 $pid 中拥有子进程 ID,它就可以使用 posix_kill($pid, SIGINT) 向子进程发送 SIGINT。

更新:显然你也可以使用 proc_openproc_terminate

关于php - 如何中断exec并杀死子进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10293292/

相关文章:

java - 从 PHP 5.2 运行 Java 的推荐方式是什么?

c++ - 原子 "check signal and enter system call"操作

c++ - 无法处理信号,导致系统调用中断

PHP json_encode JSON_PRETTY_PRINT : how to print a different format?

php - 将 ReCaptcha 与 jQuery Validate 结合使用,给出正确的响应,但给出错误

c - 调用exec后子进程会发生什么?

php exec() 没有执行命令

java - 在通过 ProcessBuilder 运行的 C 程序中捕获信号

php - 使用 php 错误更新 sql 表

python - 在 Django 中,如何立即将组的创建者添加到该组?