Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 如何中断exec并终止子进程_Php_Signals_Exec_Pcntl - Fatal编程技术网

Php 如何中断exec并终止子进程

Php 如何中断exec并终止子进程,php,signals,exec,pcntl,Php,Signals,Exec,Pcntl,我正在尝试使用exec()在PHP CLI脚本中调用一个长时间运行的shell命令。但是我一辈子都不知道如何中断PHP脚本并杀死生成的子进程。似乎只要我调用exec(),我的信号处理程序就会被忽略。下面的代码正如我所期望的那样工作;如果我将SIGTERM发送到进程,它会回显SIGTERM,并立即退出 <?php declare(ticks = 1); function sig_handler($signo) { switch ($signo) { case S

我正在尝试使用
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'),直到睡眠结束,我才到达信号处理程序。我有两个问题:

  • 如何获取信号以使用
    exec
    (或
    shell\u exec
    proc\u open
  • 捕获信号后,如何杀死由
    exec
    生成的任何子进程
  • 报告确实说:

    如果使用此函数启动程序,为了使其在后台继续运行,程序的输出必须重定向到文件或其他输出流否则将导致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
    中,它就可以使用
    posix\u kill($pid,SIGINT)
    将SIGINT发送给子进程


    更新:显然你也可以使用
    proc\u open
    proc\u terminate

    Doh!我甚至知道exec()挂起,已经在不同的上下文中遇到过。我昨天尝试了pcntl_fork、pcntl_exec方法和大约一千种其他排列,但在我的项目中无法实现。但在看到你的答案后,我创建了一个简单的测试脚本,它就像一个符咒。现在唯一的问题是,在我向我的子进程发送一个信号后,它就变成了僵尸。我通过将SIGCHLD添加到我的信号处理程序并运行pcntl_waitpid(0,$status)(也在信号处理程序中)解决了僵尸子进程。因此,如果父项收到SIGTERM,它将停止等待子项并发送SIGTERM;当孩子离开时,它会将SIGCHLD发送给父母,并得到清理…每个人都很高兴。