![Kill by pgid 如何影响新的子进程?](https://linux22.com/image/75983/Kill%20by%20pgid%20%E5%A6%82%E4%BD%95%E5%BD%B1%E5%93%8D%E6%96%B0%E7%9A%84%E5%AD%90%E8%BF%9B%E7%A8%8B%EF%BC%9F.png)
我有一个非常复杂的应用程序,它的初始化脚本和主服务作为守护进程运行。我想快速而优雅地停止它,所以我在 stop() 函数中使用了它:
group_id=$(ps -o pgid= $(cat $pidfile))
if [ ! -z $group_id ]; then
kill -- -$group_id
success
fi
它向所有子进程/线程发送终止信号。但是,如果其中一些产生新的子进程怎么办?看起来这些新的子流程没有完成他们的工作,但我需要这样做。如果我向父守护进程发送终止信号,所有子进程都会成功完成其工作,但在 shell 中它显示服务已经停止(看看我之前的主题 -如何使初始化脚本仅在所有子进程停止时才打印“OK”?)可能,我错过了一些非常明显的东西,但我仍然不知道如何以最小的努力来解决这个问题。请至少给出一些想法。
答案1
通过进程组 ID 进行终止是原子的。进程不会因为在错误的时间分叉而逃脱。为此,您可以将kill
,fork
和setpgid
视为按顺序执行的原子操作。如果一个进程运行,那么如果在 after但 before执行,if (!fork()) setpgid()
则子进程将被杀死。kill
fork
setpgid
这些新的子流程似乎没有完成他们的工作
所有子进程都会收到信号。这就是流程组的意义所在。
如果我向父守护进程发送终止信号,所有子进程都会成功完成其工作,但在 shell 中它显示服务已停止
这是可以预料的。实际上kill
在进程被终止之前返回到脚本:目标进程当前可能正在阻塞信号。在多处理器计算机上,您可能会观察到被杀死的进程在kill -9
返回后执行某些操作。
如果 shell 脚本检查主进程是否已死亡,则仅表明主进程已死亡。除了进程或进程组领导者的父进程之外,没有其他方法可以等待进程或进程组死亡。如果在启动主进程时没有进行任何设置,则没有方便的方法来检查进程组中的所有进程是否已死亡。
处理此类情况的正常方法是风门命令,这使得它干净地关闭(包括处理子进程完成的任何工作),然后才报告关闭完成并退出。以 Apache HTTPD 为例。
或者,如果您提前准备,您也许能够检测进程树。看如何获取最后一个后台应用程序的pid