我们正在运行一个PHP守护程序,它查看队列,接收工作程序作业,并产生处理它的工作程序。在继续操作之前,工作人员自己会在特定位置获得一个锁。
我们将守护进程派生为nohup后台进程。
这整个架构似乎都能工作,除了我们必须杀死进程的时候,不管是什么原因。如果我们使用-9杀死它们,就没有办法在工作进程中捕获它,并在死之前释放锁。
如果我们使用小于-9的值(如TERM或HUP),则守护进程或辅助进程似乎都不会收到它。
有没有人用更好的方法解决了这个问题?
(ps:顺便说一句,由于其他考虑,我们可能无法更改实现语言,因此请仅考虑基于PHP的解决方案)
发布于 2013-03-09 00:50:16
我也有过相关的问题。让我解释一下。我有一个像下载程序一样工作的php 'daemon‘。它定期访问feed,并从网上下载(laaaarge)内容。守护进程必须在某个时间停止,比方说早上5点,以防止它在白天使用整个带宽。我决定使用cronjob将SIGTERM发送到位于0500的守护进程。
在守护进程中,我有以下代码:
pcntl_signal(SIGTERM, array($this, 'signal_handler'));
其中signal_handler
看起来像这样:
public function signal_handler($signal) {
// some cleanup code
exit(1);
}
不幸的是,这不起作用:|
我花了一段时间才弄清楚到底是怎么回事。我想到的第一件事是,我必须在init上调用方法pcntl_signal_dispatch()
来启用信号分派。引用文档(comments):
如果你运行PHP作为命令行界面和“守护进程”(即在一个循环中),这个函数必须在每个循环中被调用,以检查是否有新的信号在等待调度。
好的,到目前为止,它似乎起作用了。但我很快意识到,在某些情况下,即使这样也不会像预期的那样工作。有时守护进程只能由kill -9
停止-就像以前一样。:
那么问题出在哪里呢?答:我的程序调用wget
通过shell_exec
下载文件。问题是,shell_exec()
阻塞会一直等待到子进程终止。在此阻塞等待期间,未进行任何信号处理,只能使用SIGKILL终止进程-这是最难的。另一个问题是,子进程必须一个接一个地终止,因为它们在杀死父亲后成为僵尸进程。
我对此的解决方案是使用proc_open()
执行子进程,并在其输出上使用stream_select()
以实现非阻塞IO。
现在它就像一个护身符一样起作用。:)如果你需要更多的信息,请不要犹豫,留下评论。
注意:如果你使用的是< 5.3版本的PHP,那么你必须使用`
declare(ticks=1);
而不是pcntl_signal_dispatch()
。关于这一点,您可以参考pcntl_signal()
的文档。但如果可能的话,您应该升级到PHPP5.3 >=
发布于 2013-03-15 14:27:02
只需添加标记即可解决此问题:
// tick use required as of PHP 4.3.0
declare(ticks = 1);
不去管它会导致我的代码不能工作。
*(不幸的是,pcntl_signal的文档并没有以更吸引人的方式提到它。)*
发布于 2013-03-08 11:38:50
您需要捕获信号(SIGTERM)。这可以通过函数pcntl_signal来实现。这将为您提供在调用exit之前执行任何必要功能的选项。
https://stackoverflow.com/questions/15286264
复制相似问题