使用PHP启动守护进程

11

我需要在网站上启动和停止一个守护进程。目前我的做法是:

exec("sudo /etc/init.d/daemonToStart start");
守护进程已经启动,但Apache/PHP无响应。运行ps aux发现sudo变成了僵尸进程,从而杀死了所有进一步的进展。当尝试从PHP启动守护进程时,这是正常行为吗?是的,Apache有权执行/etc/init.d/daemonToStart命令。我修改了/etc/sudoers文件以允许它这样做。不,我没有允许Apache能够执行任何类型的命令,只允许少数几个以使网站工作。无论如何,回到我的问题,有没有一种方法可以允许PHP启动守护进程,而不会创建僵尸进程?我问这个问题是因为当我反过来停止已经启动的守护进程时,一切都很顺利。

应该有一个 start 参数吗? - ZeissS
是的,我忘记在问题中添加了。但是,在我的代码中,我已经有它了。不过,为了完整起见,我会编辑一下问题。 - ThaMe90
3个回答

13

尝试在命令后面添加> /dev/null 2>&1 &

像这样:

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

为了以防万一,这里是它的功能和原因:

  • > /dev/null - 将标准输出重定向到 /dev/null(也就是黑洞)
  • 2>&1 - 将标准错误输出重定向到标准输出(也将其作为黑洞处理)
  • & 分离进程并在后台运行

谢谢进一步的解释,但由于输出被黑洞化,任何在守护程序启动后应该执行的代码也被省略了。我必须检查进程是否已经启动,但是那段代码从未被触发... - ThaMe90
1
当您使用此方法启动进程时,它应输出已创建的进程的PID。您可以获取此PID,然后(例如)执行 ps | grep $pidOfProcessYouJustStarted 以确保它正在运行。 - DaveRandom
实际上,你可以执行“ps | grep /etc/init.d/daemonToStart”来做同样的事情... - DaveRandom
我知道,我已经在做了。 ;) 然而,似乎那段代码从未被执行过,因为我的浏览器没有弹出我所呈现的结果值的警报。但是我的日志显示该代码实际上正在运行。再次感谢。 - ThaMe90

2

我遇到了同样的问题。

我同意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);

0

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

  • 按照DaveRandom的答案,在命令的末尾添加/dev/null 2>&1 &。这将把错误重定向到标准输出。然后,您可以使用此输出进行调试。
  • 确保您的Web服务器用户的PATH包含在守护程序脚本中引用的所有二进制文件。您可以通过调用exec('echo $PATH; whoami;)来实现这一点。这将告诉您PHP正在运行的用户及其当前的PATH变量。

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