如果设置了pcntl_signal(),我可以依赖在 SIGTERM 上调用register_shutdown_function()吗?
我正在处理一个定期调用后台进程的应用程序。其中一个被cron调用,但我正在寻找更强大的东西,所以我将其转换为在主管下运行。(它可能会运行 10 分钟,在此期间,它可以检测要完成的工作或空闲状态。退出后,Supervisor 将自动重生一个干净的实例。
由于 Supervisor 更擅长确保只有指定数量的实例并行运行,因此我可以运行它们更长时间。但是,这确实意味着我的进程更有可能直接从接收终止信号,或者因为它们已通过 Supervisor 停止。因此,我正在尝试如何在PHP中处理这个问题。kill
看起来基本的解决方案是像这样使用pcntl_signal():
declare(ticks = 1);
pcntl_signal(SIGTERM, 'signalHandler');
pcntl_signal(SIGINT, 'signalHandler');
function signalHandler($signal) {
switch($signal) {
case SIGTERM:
case SIGINT:
echo "Exiting now...\n";
exit();
}
}
但是,我的代码中有几个点可以仔细处理关闭。一种方法是让一个处理程序调用这些不同的内容,但这需要一些重构,我想避免这种情况。另一种方法是在我需要的地方添加它,但不幸的是,似乎一次只能安装一个处理程序。pcntl_signal()
但是,看起来我可以使用register_shutdown_function()
。这本身不会捕获或其他终止 sigs,手册在这一点上非常清楚:^C
如果进程被 SIGTERM 或 SIGKILL 信号杀死,则不会执行关机功能
令人惊讶的是,我发现如果我只做一个出口,那么关闭处理程序确实被调用了。此外,由于可以有许多关闭处理程序,这很好地解决了我的问题 - 我的代码中希望优雅地处理终止的每个类都可以捕获和管理自己的关闭。pcntl_signal()
我最初的问题是,为什么这有效?我尝试过在没有信号处理程序的情况下注册关机功能,并且似乎没有像手册所说的那样调用它。我猜PHP使进程保持活动状态以便处理信号,这会导致调用关闭处理程序?
另外,当手册对它产生怀疑时,我可以依靠这种行为吗?我正在使用PHP 5.5,并且还不想升级到PHP7。因此,我对这是否适用于5.5和5.6以及各种发行版感兴趣。
当然,无论它是否(或不会)在7.0和/或7.1上运行,也会很有趣 - 我知道尽管在7.1中会以不同的方式处理刻度,因此它有不同的行为的可能性更大。