【问题标题】:Why child process still alive after parent process was killed in Linux?为什么在Linux中父进程被杀死后子进程仍然活着?
【发布时间】:2012-01-21 22:23:51
【问题描述】:

有人告诉我,当你在 linux 中杀死一个父进程时,子进程会死。
但我对此表示怀疑。所以我写了两个bash脚本,father.sh会调用child.sh

这是我的脚本:

现在我运行bash father.sh,你可以检查它ps -alf

然后我被kill -9 24588杀死了father.sh,我猜想应该终止子进程但不幸的是我错了。

谁能解释为什么?

谢谢

【问题讨论】:

  • 我认为你可以剪掉 80% 的文字和所有图片,而仍然保留这个问题中重要的所有内容。

标签: linux bash process


【解决方案1】:

不,当你单独杀死一个进程时,它不会杀死子进程。

如果您希望给定组的所有进程都接收信号,则必须将信号发送到 进程组

例如,如果您的父进程 id 的代码为 1234,则您必须指定 parentpid,添加符号减号,后跟您的父进程 id:

kill -9 -1234

否则,孤儿将链接到init,如您的第三个屏幕截图所示(孩子的 PPID 已变为 1)。

【讨论】:

  • 其中thepidhere通常是父进程的PID,但可以使用ps -eo "%p %r %c %a"确定。 +1。
  • 进程组ID与父ID相同。您能否详细说明如何阻止它们
  • 只是为了澄清 fge 的命令以防不明显,您将父 id 作为负数传递,例如如果父 pid 是 1234,你想杀死 -1234
  • 这对我不起作用。如果我有PID 123 的进程并且我执行kill -9 -123 我有以下错误-bash: kill: (-123) - No such process。我在 Centos 6 上运行
  • 如果其他人在运行kill -9 -27541 时像我一样kill: invalid option -- '2',那就做kill -9 -- -27541
【解决方案2】:

-bash: kill: (-123) - 没有这样的进程

在交互式 Terminal.app 会话中,当启用作业控制/监视模式时,前台进程组 ID 号和后台进程组 ID 号在设计上是不同的。换句话说,如果您在启用了作业控制的 Terminal.app 会话中后台执行命令,则后台进程的$! pid 实际上是一个新的进程组 ID 号 (pgid)。

但是,在没有启用作业控制的脚本中,情况可能并非如此!后台进程的pid可能不是新的pgid而是正常的pid!这就是导致错误消息-bash: kill: (-123) - No such process 的原因,它试图杀死一个进程组,但只为kill 命令指定一个正常的pid(而不是pgid)。

# the following code works in Terminal.app because $! == $pgid
{
sleep 100 &
IFS=" " read -r pgid <<EOF
$(ps -p $! -o pgid=)
EOF
echo $$ $! $pgid
sleep 10
kill -HUP -- -$!
#kill -HUP --  -${pgid}  # use in script
}

【讨论】:

  • 这回答了一个完全不同的问题
  • 但实际上解释了我的问题:)
【解决方案3】:
pkill -TERM -P <ProcessID>

这会杀死父母和孩子

【讨论】:

  • 这是否也会杀死祖父母或曾祖父母匹配ProcessID的进程?
【解决方案4】:

通常杀死父母也会杀死孩子。

您看到孩子在杀死父亲后仍然活着的原因是因为孩子只有在它“选择”(内核选择)来处理 SIGKILL 事件后才会死。它不必马上处理。您的脚本正在运行 sleep() 命令(即在内核中),该命令在睡眠完成之前不会唤醒以处理任何事件。

为什么 PPID #1?父级已死,不再在进程表中。 child.sh 现在没有莫名其妙地链接到 init。它根本没有运行的父级。说它与 init 相关联会产生这样一种印象,即如果我们以某种方式离开 init,则 init 可以控制关​​闭进程。它还给人一种印象,即杀死父母将使祖父母成为孩子的主人。两者都不是真的。该子进程仍然存在于进程表中并且正在运行,但在处理 SIGKILL 之前,不会处理基于其进程 ID 的新事件。这意味着孩子是一个僵尸前,行尸走肉,有被贴上标签的危险。

在进程组中杀死是不同的,用于杀死兄弟,和进程组#。同样重要的是要注意“杀死进程”本身并不是“杀死”,以人类的方式,您希望进程被销毁并且所有内存都返回,就好像它从来没有一样。它只是将一个特定事件(在许多事件中)发送到进程以供其处理。如果进程没有正确处理它,那么一段时间后操作系统会出现并强制“清理”它。

它(杀死)不会立即发生,因为孩子(甚至父母)可能已将某些内容写入磁盘并等待 I/O 完成或执行其他可能危及系统稳定性或文件的关键任务完整性。

【讨论】:

  • Beracah,看来您只是虚构了整个回复。接受的答案是正确的,我留给你这个链接:man7.org/linux/man-pages/man7/signal.7.html 并引用“信号 SIGKILL 和 SIGSTOP 不能被捕获、阻止或忽略。”
  • 超级误导的答案。杀死父母通常不会杀死孩子。 SIGKILL 是不可忽视的。它可能阻塞的唯一原因是系统调用挂起并且进程卡在内核模式下。
  • 是的,这是 100% 正确的误导,如果我们严格按照字面意思执行当前是在内核模式还是在用户模式下,则只有 90% 正确。又名,对“选择”这个词很挑剔。当然,你对“选择”这个词挑剔是对的,因为它暗示进程正在自己处理信号。但是接受的答案是不正确的,特别是因为father.sh 正在运行sleep。杀死孩子的唯一方法是杀死组,但杀死组绝对是一个不同的答案,因为进程是分别被杀死的。
  • 只是为了澄清一下,OP 的问题字面上是,“为什么当父进程卡在内核模式时子进程也不会被杀死?”它不是这样表达的,但就是这样。这也是为什么接受的答案不正确的原因。当只有杀死父进程才是正确答案时,它可能会导致不同的用户杀死整个进程组。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-09
  • 1970-01-01
  • 2011-09-23
  • 1970-01-01
  • 1970-01-01
  • 2010-12-02
相关资源
最近更新 更多