php exec造成僵尸进程,将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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值