Kill by pgid 如何影响新的子进程?

Kill by pgid 如何影响新的子进程?

我有一个非常复杂的应用程序,它的初始化脚本和主服务作为守护进程运行。我想快速而优雅地停止它,所以我在 stop() 函数中使用了它:

group_id=$(ps -o pgid= $(cat $pidfile))
if [ ! -z $group_id ]; then
    kill -- -$group_id
success
fi

它向所有子进程/线程发送终止信号。但是,如果其中一些产生新的子进程怎么办?看起来这些新的子流程没有完成他们的工作,但我需要这样做。如果我向父守护进程发送终止信号,所有子进程都会成功完成其工作,但在 shell 中它显示服务已经停止(看看我之前的主题 -如何使初始化脚本仅在所有子进程停止时才打印“OK”?)可能,我错过了一些非常明显的东西,但我仍然不知道如何以最小的努力来解决这个问题。请至少给出一些想法。

答案1

通过进程组 ID 进行终止是原子的。进程不会因为在错误的时间分叉而逃脱。为此,您可以将kill,forksetpgid视为按顺序执行的原子操作。如果一个进程运行,那么如果在 after但 before执行,if (!fork()) setpgid()则子进程将被杀死。killforksetpgid

这些新的子流程似乎没有完成他们的工作

所有子进程都会收到信号。这就是流程组的意义所在。

如果我向父守护进程发送终止信号,所有子进程都会成功完成其工作,但在 shell 中它显示服务已停止

这是可以预料的。实际上kill在进程被终止之前返回到脚本:目标进程当前可能正在阻塞信号。在多处理器计算机上,您可能会观察到被杀死的进程在kill -9返回后执行某些操作。

如果 shell 脚本检查主进程是否已死亡,则仅表明主进程已死亡。除了进程或进程组领导者的父进程之外,没有其他方法可以等待进程或进程组死亡。如果在启动主进程时没有进行任何设置,则没有方便的方法来检查进程组中的所有进程是否已死亡。

处理此类情况的正常方法是风门命令,这使得它干净地关闭(包括处理子进程完成的任何工作),然后才报告关闭完成并退出。以 Apache HTTPD 为例。

或者,如果您提前准备,您也许能够检测进程树。看如何获取最后一个后台应用程序的pid

相关内容