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