php - 将 PHP 进程作为守护进程运行,同时从后台安全地终止它

标签 php kill-process daemons

我们正在运行一个 PHP 守护进程,它查看队列、接收工作任务并派生工作人员来处理它。在继续之前,工作人员自己会锁定特定位置。

我们将守护进程生成为 nohup 后台进程。

整个体系结构似乎都可以工作,除非我们出于某种原因必须终止进程。如果我们使用 -9 杀死它们,则无法将其困在工作进程中并在死亡前释放锁。

如果我们使用小于 -9 的值(如 TERM 或 HUP),它似乎不会被守护进程或工作进程接收。

有没有人以更好的方式解决了这个问题?

(ps:顺便说一句,出于其他考虑,我们可能无法更改我们的实现语言,所以请只考虑基于 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);
}

不幸的是,这没有用:|

我花了一些时间才弄清楚发生了什么。我想到的第一件事是我必须调用方法 pcntl_signal_dispatch()在 init 上启用信号调度。引自文档 ( 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 - 将 PHP 进程作为守护进程运行,同时从后台安全地终止它,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15286264/

相关文章:

php - 如何防止 &lt;meta http-equiv ="refresh"> 攻击?

C++通过exec函数杀死子进程,但不杀死父进程和正常运行时间

没有 Rails 的 Ruby 的 `.present?`?

ruby - 停止守护进程会破坏我的数据吗?

php - 使用 Laravel 授权中间件

php - CakePHP - 访问多个表和类别的页面

Python 子进程 pkill

linux - k8s liveness probe 失败时发送给容器中运行的进程的信号是什么?杀死或学期

ruby - 处理守护进程的输入和输出

php - Javascript document.write(metadata) 对 SEO 有效吗?