我正在尝试使用 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 结束之前我不会到达我的信号处理程序。我有两个问题:
- 如何获取信号以使用
exec
(或shell_exec
或proc_open
)? - 捕获信号后,如何终止
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_open
和 proc_terminate
。
关于php - 如何中断exec并杀死子进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10293292/