【问题标题】:Starting a daemon from PHP从 PHP 启动守护进程
【发布时间】:2012-01-13 07:08:21
【问题描述】:

对于网站,我需要能够启动和停止守护进程。我目前正在做的是

exec("sudo /etc/init.d/daemonToStart start");

守护进程已启动,但 Apache/PHP 挂起。执行ps aux 显示sudo 本身变成了一个僵尸进程,有效地杀死了所有进一步的进展。尝试从 PHP 启动守护进程时这是正常行为吗?

是的,Apache 有权执行/etc/init.d/daemonToStart 命令。我更改了 /etc/sudoers 文件以允许它这样做。不,我没有让 Apache 能够执行任何类型的命令,只是允许网站运行的少数几个命令。

无论如何,回到我的问题,有没有办法让 PHP 以不创建僵尸进程的方式启动守护进程?我问这个是因为当我做相反的事情时,停止一个已经启动的守护进程,工作得很好。

【问题讨论】:

  • 不应该有start 参数吗?
  • 没错,我忘了在问题中添加这个。在我的代码中,我确实拥有它。但是,为了完整起见,我会编辑问题。

标签: php daemon zombie-process


【解决方案1】:

尝试将> /dev/null 2>&1 & 附加到命令中。

所以这个:

exec("sudo /etc/init.d/daemonToStart > /dev/null 2>&1 &");

以防万一您想知道它的作用/原因:

  • > /dev/null - 将 STDOUT 重定向到 /dev/null(换句话说,黑洞)
  • 2>&1 - 将 STDERR 重定向到 STDOUT(黑洞也是如此)
  • & 分离进程并在后台运行

【讨论】:

  • 感谢您的进一步解释,但由于输出是黑洞,因此​​本应在守护程序启动后执行的任何代码也被允许。我必须检查进程是否已启动,但该代码从未被触发...
  • 当你使用这个方法启动一个进程时,它应该输出创建的进程的PID。您可以使用它,然后(例如)执行ps | grep $pidOfProcessYouJustStarted 以确保它正在运行。
  • 其实你可以执行ps | grep /etc/init.d/daemonToStart来做同样的事情...
  • 我知道,我已经这样做了。 ;) 似乎该代码从未执行过,因为我的浏览器没有向我显示我提供的结果值的警报。但我的日志显示代码实际上正在运行。再次感谢。
【解决方案2】:

我从未尝试过从 PHP 启动守护程序,但我已经尝试过运行其他 shell 命令,但遇到了很多麻烦。以下是我过去尝试过的一些事情:

  • 根据 DaveRandom 的回答,将 /dev/null 2>&1 & 附加到命令末尾。这会将错误重定向到标准输出。然后,您可以使用此输出进行调试。
  • 确保您的网络服务器的用户路径包含您的守护程序脚本中所有引用的二进制文件。您可以通过调用exec('echo $PATH; whoami;) 来完成此操作。这将告诉您 PHP 正在运行的用户,以及当前的 PATH 变量。

【讨论】:

    【解决方案3】:

    我遇到了同样的问题。

    我同意 DaveRandom,你必须抑制每个输出(stdout 和 stderr)。但是不需要在另一个以'&'结尾的进程中启动:exec()函数不能再检查返回码,即使有错误也会返回ok...

    而且我更喜欢将输出存储在临时文件中,而不是“黑洞”。 工作解决方案:

    $temp = tempnam(sys_get_temp_dir(), 'php');
    exec('sudo /etc/init.d/daemonToStart >'.$temp.' 2>&1');
    

    读取文件内容后,删除临时文件:

    $output = explode("\n", file_get_contents($temp));
    @unlink($temp);
    

    【讨论】: