使用popen()打开的进程如何终止?

10

我使用popen()打开了一个长时间运行的进程。为了调试,我想在它完成之前终止进程。但是调用pclose()会一直阻塞直到子进程完成。

如何杀死这个进程?我没有找到简单的方法来获取popen()返回资源中的pid,以便可以向其发送信号。

我想我可以尝试使用某种命令行技巧将pid蒙混到输出中...


这不是一个真正的答案,因为它是针对C而不是PHP的,但请参考以下链接以获取建议:http://www.monkey.org/openbsd/archive/misc/0112/msg00360.html - Nate C-K
3个回答

8

好的,找到了解决方案:我改回使用 proc_open() 而不是 popen()。然后就很简单了:

$s = proc_get_status($p);
posix_kill($s['pid'], SIGKILL);
proc_close($p);

我也遇到了使用proc_open()时的同样问题,所以我尝试了更简单的popen(),希望这会有所帮助。当时我没有意识到,同时 pclose()proc_close()都会阻塞直到子进程终止。一旦你意识到这一点,那么你就必须杀死子进程。而要杀死子进程,你需要pid,而这在popen()中并不容易获得。proc_open()可以完成popen()的所有功能,还有更多的功能。 - Frank Farmer
Variable - mauris
@thephpdeveloper 现在 SO 给我一个 "您可以明天接受您自己的答案" 的错误提示。 - Frank Farmer
2
请查看 http://www.php.net/manual/en/function.proc-terminate.php#81353,因为您需要杀死所有子进程(如果有)。 - EGL 2-101

0
您可以通过以下方式找到pid,并检查它是否真的是您的父进程:
// Find child processes according to current pid
$res = trim(exec('ps -eo pid,ppid |grep "'.getmypid().'" |head -n2 |tail -n1'));
if (preg_match('~^(\d+)\s+(\d+)$~', $res, $pid) !== 0 && (int) $pid[2] === getmypid())
{
    // I'm the parent PID, just send a KILL
    posix_kill((int) $pid[1], 9);
}

在快速CGI PHP服务器上运行得非常好。


0

1
棘手的部分是要好好地找出要杀死哪个pid :) 一旦确定了正确的pid,就可以调用php的posix_kill()。我想回过头来看,我本可以从ps中grep子进程列表,因为很容易找到自己的pid。 - Frank Farmer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接