【问题标题】:PHP - Kill proc_open() process on different file?PHP - 杀死不同文件上的 proc_open() 进程?
【发布时间】:2016-01-28 20:58:23
【问题描述】:

我正在使用proc_open() 创建一个后台进程,并且想知道如何在我的后台进程仍在运行时从不同的文件或操作取消或停止此后台进程?

这是我的代码:

$errorLog = './error.log';
$descriptorspec = array(
    0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
    1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
    2 => array("file", $errorLog, "a") // stderr is a file to write to
);
proc_open("/var/bin/php /home/hello/myscript.php &", $descriptorspec, $pipes);

我已经阅读了有关proc_terminate($process) 的信息,但似乎需要proc_open() 返回的内容才能停止该过程。在同一个脚本中没有proc_open() 的情况下,有什么办法可以阻止它?

【问题讨论】:

  • 您可以尝试将 proc_open 中的 PID 写入文件,然后让辅助脚本检查该文件是否存在,获取 PID,然后尝试终止它。
  • 是的,不要使用proc_terminate(),而是使用posix_kill()或类似的东西。

标签: php process proc-open


【解决方案1】:

执行此操作的典型方法是让子脚本获取其进程 ID(在 PHP 中使用 getmypid())并写出包含此 pid 的文件(通常类似于 myscript.pid)。

然后任何其他想要终止该脚本的东西都会检查 pid 文件是否存在,读取它,(并可能为了稳健性,检查该 pid 处的目标进程是什么),然后终止目标进程。在 PHP 中,您可以使用 posix_kill() 来实现。 (通常,您可以发送SIGTERMSIGKILL,但SIGHUPSIGINT,甚至SIGUSR1SIGUSR2 都是合适的,具体取决于您希望子进程在收到信号时执行的操作。

或者,父进程可以使用proc_get_status() 获取子进程的 pid,并将 pid 写入某处以供以后使用。 (如果您需要运行多个子实例和/或无法以这种方式修改子实例,这可能更合适。)

另外,需要注意的是,在您对proc_open 的调用中,您正试图要求外壳程序跨越后台进程。这是完全没有必要的。 proc_open 本身就是这样做的,通过强制外壳成为中介,您实际上连接到外壳,而不是您尝试启动的进程。 (这意味着当你的脚本存在时,这也会导致 shell 杀死孩子,而不是孩子继续在后台运行。)

【讨论】:

  • 我明白了,但是当我在 Windows 上试用它时,我的脚本似乎一直在加载,因为它有很长的过程以及为什么我将它作为后台运行,并且与 linux 相同,我在命令末尾添加& 以将其作为后台运行。顺便说一句,你能给我解释一下SIGTERMSIGKILL 是什么,因为我看不懂php.net/manual/en/pcntl.constants.php