【问题标题】:Background process getting killed when its parent is terminated?父进程终止时后台进程被杀死?
【发布时间】:2016-02-11 23:10:28
【问题描述】:

我的代码看起来像这样

function doTheThing{
  # a potentially infinite while loop...
}
# other stuff...
doTheThing &
trap "kill $!" SIGINT SIGTERM

奇怪的是,当我在循环完成之前 ctrl-C 退出父进程时,我收到一条消息,指出该进程不存在。此外,如果我摆脱了陷阱,我无法使用 ps -aF 找到该进程。看起来后台进程在其父进程终止时被杀死,但我的理解是这不应该发生。我只是想确保我可以安全地避开陷阱并且不会到处留下僵尸进程。

【问题讨论】:

  • Control-C 杀死整个进程组,而不仅仅是进程。
  • 僵尸进程是一个已经死亡但其父进程尚未调用wait 的进程。如果父级被杀死,僵尸会被init 继承,等待它。
  • 所以要明确一点,你是说如果我摆脱了陷阱,我不会留下任何额外的进程?
  • barmar 的意思是,如果这些进程仍在运行,它们就不是僵尸。如果您使用 ctrl-C 向进程组发送 SIGINT,那么子进程将收到信号。 (但可能不会终止。)但是如果您从另一个进程通过kill 发送信号,或者如果父进程因其他原因终止,它们不会。

标签: bash shell sh kill


【解决方案1】:

POSIX specification 表示当您键入中断字符(通常为 Control-C)时,SIGINT 被发送到前台进程组。所以只要后台进程和调用它的脚本在同一个进程组中运行,它就会和脚本进程同时接收到信号。

Shell 通常使用进程组来实现作业控制,默认情况下,这仅在交互式 shell 中启用,而不是在运行脚本的 shell 中启用。在自己的进程组中运行函数没有标准方法,但您可以使用setsid 在新会话中运行它,这是比进程组更高级别的分组。那么它就不会收到中断了。

不过,您可能仍想编写一个 trap 命令来杀死 EXIT 上的函数。

doTheThing&
trap "kill $!" EXIT

因为退出脚本不会自动杀死进程组的其余部分。

【讨论】:

  • 幸运的是,这是一个启动长时间运行的开发服务器的脚本。据我所知,脚本结束的唯一方法是 sigint sigterm 等,或者服务器本身的段错误/致命错误,所以我认为我不需要担心
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-09
  • 1970-01-01
  • 1970-01-01
  • 2010-12-02
  • 2010-12-08
  • 1970-01-01
相关资源
最近更新 更多