21

考虑以下,它sleep 60在后台运行然后退出:

$ cat run.sh 
sleep 60&
ps
echo Goodbye!!!
$ docker run --rm -v $(pwd)/run.sh:/run.sh ubuntu:16.04 bash /run.sh
  PID TTY          TIME CMD
    1 ?        00:00:00 bash
    5 ?        00:00:00 sleep
    6 ?        00:00:00 ps
Goodbye!!!

这将启动一个带有bashPID1 的 Docker 容器。然后它 fork/execs 一个sleep进程,然后bash退出。当 Docker 容器死亡时,sleep进程也会以某种方式死亡。

我的问题是:sleep进程被杀死的机制是什么?我尝试SIGTERM在子进程中进行捕获,但这似乎没有被绊倒。SIGKILL我的假设是,在关闭容器正在使用的 cgroup 时,某些东西(Docker 或 Linux 内核)正在发送,但我在任何地方都找不到任何文档来澄清这一点。

编辑我最接近的解释是来自baseimage-docker的以下引用:

如果您的 init 进程是您的应用程序,那么它可能只会关闭自己,而不是容器中的所有其他进程。然后内核将强行杀死那些其他进程,而不给它们正常关闭的机会,这可能会导致文件损坏、过时的临时文件等。你真的想优雅地关闭所有进程。

所以至少按照这个,意思是当容器退出时,内核会向所有剩余的进程发送一个SIGKILL。但是我仍然希望清楚它是如何决定这样做的(即,它是 cgroups 的一个特性吗?),理想情况下,一个更权威的来源会很好。

4

1 回答 1

7

好的,我似乎找到了一些更确凿的证据,证明这实际上是 Linux 内核在终止。在clone(2)手册页中,有这个有用的部分:

CLONE_NEWPID(自 Linux 2.6.24 起)

在新命名空间中创建的第一个进程(即使用 CLONE_NEWPID 标志创建的进程)具有 PID 1,并且是命名空间的“init”进程。在命名空间中孤立的子进程将重新成为该进程的父进程,而不是 init(8)。与传统的 init 进程不同,PID 命名空间的“init”进程可以终止,如果终止,则命名空间中的所有进程都将终止。

不幸的是,这对于命名空间中的进程是如何终止的仍然很模糊,但这可能是因为,与正常的进程退出不同,进程表中没有留下任何条目。不管是什么情况,似乎很清楚:

  • 内核本身正在杀死其他进程
  • 他们不会以允许他们任何机会进行清理的方式被杀死,使其(几乎?)与 SIGKILL 相同
于 2016-09-28T16:05:36.383 回答