系统相关
首页 > 系统相关> > 将PHP进程作为守护进程运行,同时从后台安全地将其杀死

将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