我有以下流程树
test1.sh
\- test2.sh
\- sleep 600
通常如果我终止 test1.sh 进程,子进程 test2.sh 和 sleep 600 将继续运行。但是如果我通过发送信号(SIGSTOP或SIGTSTP)暂停 sleep 600 进程,然后终止 test1.sh 进程,那么 test2.sh 和 sleep 600 将退出。为什么呢?
这是我的测试程序:
test1.sh
#!/bin/sh
./test2.sh
test2.sh
#!/bin/sh
sleep 600
测试步骤:
运行test1.sh
$ ./test1.sh
打开新控制台并暂停子进程。
$ kill -19<睡眠pid>或者杀死-20<睡眠pid>
终止父进程test1.sh
$ kill< test1.sh pid>
您将找到after step3,test2.sh和sleep 600退出。
如果我只运行step1和step3,忽略step2,则test2.sh和sleep 600进程将不会退出。
任何人都能解释一下吗?非常感谢。
答案 0 :(得分:1)
当你杀死进程test1.sh
时,你会离开test2.sh
孤儿,这样你就需要知道操作系统中孤儿进程会发生什么。
当进程test2.sh
正在运行且其父进程终止时,操作系统会将其移至init进程并继续执行。因此,即使您已杀死test2.sh
,结果仍然是sleep
和test1.sh
进程仍在运行。
当进程sleep
停止(信号20)并且他的父进程死亡时,OS会尝试将其移动到init进程。但是,由于进程已停止,并且将不再有任何能够恢复它的tty(因为其父级已经死亡),操作系统可能决定对该进程执行其他操作。在您的情况下,它会与SIGKILL一起消失,以避免系统周围出现许多已停止的孤立进程的问题。由于sleep
进程已退出,test2.sh
进程也会结束。
从GNU手册页:
当进程停止时,不再向其发送信号 直到它继续,除了SIGKILL信号和(显然)SIGCONT 信号。信号被标记为待处理,但直到 这个过程还在继续。 SIGKILL信号总是导致终止 的过程,不能被阻止,处理或忽略。您可以 忽略SIGCONT,但它总是导致进程继续 无论如何,如果它被停止。向进程发送SIGCONT信号会导致 要丢弃该进程的任何待处理停止信号。同样, 当进程的任何挂起的SIGCONT信号被丢弃时 收到一个停止信号。
孤立进程组中的进程时(请参阅孤立进程 组)接收SIGTSTP,SIGTTIN或SIGTTOU信号,但不接收 处理它,过程不会停止。停止这个过程会 可能不是很有用,因为没有shell程序会 注意它停止并允许用户继续它。反而会发生什么 取决于您使用的操作系统。有些系统可能会这样做 没有;其他人可能会提供另一个信号,例如SIGKILL或 SIGHUP。在GNU / Hurd系统上,该过程随SIGKILL而死;这个 避免了许多停止,孤立的进程的问题 系统。
顺便说一句,如果你愿意杀死它们,你总是可以在主进程上添加trap
来捕获信号并正确退出孩子。