将PHP进程作为守护进程运行,同时从后台安全地将其杀死
作者:互联网
我们正在运行一个PHP守护进程,它会查看队列,接收工作程序作业并生成工作程序来处理它.在继续之前,工人自己获得对特定位置的锁定.
我们将守护进程产生为nohup后台进程.
这整个架构似乎都有效,除非我们因为某种原因必须杀死进程.如果我们使用-9杀死它们,则无法将其捕获到工作进程中并在死亡之前释放锁定.
如果我们使用小于-9的任何东西(如TERM或HUP),那么守护进程或工作进程似乎都没有收到它.
有没有人以更好的方式解决这个问题?
(ps:BTW,由于其他考虑因素,我们可能无法更改我们的实现语言,因此请仅考虑基于PHP的解决方案)
解决方法:
我也有过相关的问题.让我解释.我有一个php’守护进程’,就像一个下载程序.它定期访问订阅源并从网上下载(laaaarge)内容.守护进程必须在某个时间停止,让我们说早上0500,以防止它在白天使用整个带.我决定使用cronjob在0500将SIGTERM发送给守护进程.
在守护进程中,我有以下代码:
pcntl_signal(SIGTERM, array($this, 'signal_handler'));
其中signal_handler看起来像这样:
public function signal_handler($signal) {
// some cleanup code
exit(1);
}
不幸的是,这不起作用:|
我花了一点时间才知道发生了什么.我想到的第一件事是我必须在init上调用方法pcntl_signal_dispatch()
才能启用信号调度.从文档引用(comments):
If you are running PHP as CLI and as a “daemon” (i.e. in a loop), this function must be called in each loop to check if new signals are waiting dispatching.
好吧,到目前为止,它看起来很有效.但我很快意识到,在某些条件下,即使这样也无法按预期工作.有时守护进程只能被kill -9停止 – 就像之前一样. :|
那么问题是什么?答案:我的程序叫wget通过shell_exec下载文件.问题是,shell_exec()阻塞等待子进程终止.在此阻塞等待期间,没有信号处理完成,该过程只能使用SIGKILL终止 – 这很难.还有一个问题是,在杀死父亲之后,子进程必须逐个终止,因为它们变成了僵尸进程.
我的解决方案是使用proc_open()执行子进程,并在其输出上使用stream_select()用于非阻塞IO.
现在它就像一个魅力. :)如果您需要进一步的信息,请不要犹豫,发表评论.
注意如果您正在使用PHP< 5.3那么你将不得不使用`
declare(ticks=1);
而不是pcntl_signal_dispatch().您可以参考pcntl_signal()
的文档.但是如果可能的话,你应该升级到PHP> = 5.3
标签:php,daemons,kill-process 来源: https://codeday.me/bug/20190625/1285555.html