gpt4 book ai didi

bash - 如何在 docker 中使用 bash 作为 PID1 重现僵尸进程?

转载 作者:行者123 更新时间:2023-11-29 09:06:05 24 4
gpt4 key购买 nike

我有一个在 PID1 上运行 bash 的 Docker 容器,它反过来运行一个长时间运行的(复杂的)服务,有时会产生以 PID1 上的 bash 为父级的僵尸进程。这些僵尸似乎从未被收割过。

我正在尝试在最小容器中重现此问题,以便我可以测试缓解措施,例如使用适当的 init 作为 PID1 而不是 bash。

但是,我一直无法重现僵尸进程。 PID1 的 bash 似乎收获了 child ,甚至是从另一个进程继承的 child 。

这是我尝试过的:

docker run -d ubuntu:14.04 bash -c \
'bash -c "start-stop-daemon --background --start --pidfile /tmp/sleep.pid --exec /bin/sleep -- 30; sleep 300"'

我的期望是 start-stop-daemon 会双叉创建一个父级为 PID1 的 bash 的进程,然后执行到 sleep 30,当sleep exits 我希望进程保持僵尸状态。 sleep 300 模拟长时间运行的服务。

但是,bash 获取进程,我可以通过在 bash 进程上运行 strace 来观察(从运行 docker 的主机):

$ sudo strace -p 2051
strace: Process 2051 attached
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 9
wait4(-1,

我正在运行 docker 1.11.1-rc1,尽管我对 docker 1.9 有相同的体验。

$ docker --version
Docker version 1.11.1-rc1, build c90c70c
$ uname -r
4.4.8-boot2docker

鉴于 strace 显示 bash 收获(孤儿) child ,bash 是 docker 容器中合适的 PID1 吗?还有什么可能导致我在更复杂的容器中看到僵尸?我怎样才能重现?

编辑:

我设法将 strace 附加到一个出现问题的实时容器上的 bash PID1。

Process 20381 attached
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 11185
wait4(-1, [{WIFSIGNALED(s) && WTERMSIG(s) == SIGTERM}], 0, NULL) = 11191
wait4(-1, [{WIFSIGNALED(s) && WTERMSIG(s) == SIGTERM}], 0, NULL) = 11203
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 11155
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 11151
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 11152
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 11154
wait4(-1, [{WIFSIGNALED(s) && WTERMSIG(s) == SIGTERM}], 0, NULL) = 11332
...

不确定所有这些退出的进程到底是什么,但是没有一个 PID 与 docker exec $id ps aux | 显示的少数已失效僵尸进程的 PID 匹配grep 已失效

也许诀窍是捕捉它的运行并查看 wait4() 在仍然是僵尸的进程上返回什么...

最佳答案

我还想验证我的 jenkins 容器从站是否可以生成僵尸。

因为我的图像运行 scl 二进制文件,它又启动了 java JLNP 客户端,所以我在 jenkins slave groovy 脚本控制台中执行了以下操作:

def process=new ProcessBuilder("bash", '-c', 'sleep 10 </dev/null &>/dev/null & disown').redirectErrorStream(true).start()
println process.inputStream.text
println " ps -ef".execute().text

僵尸已经生成。那就是 scl 以 PID 1 结尾。

然后我看了你的问题,决定试试 bash。我的第一次尝试是将 ENTRYPOINT 更改为:

bash -c "/usr/bin/scl enable rh-ror42 -- /usr/local/bin/run-jnlp-client $1 $2" --

然后查看 ps 输出,我意识到 PID 1 不是 bash 但实际上 PID 1 仍然是 scl 二进制文件。最后将命令更改为:

bash -c "/usr/bin/scl 启用 rh-ror42 --/usr/local/bin/run-jnlp-client $1 $2 ; ls"--

那是在 scl 命令之后添加一些随机的第二个命令。瞧——bash 变成了 PID 1,再也没有僵尸生成了。

查看您的示例,我发现您使用多个命令运行 bash -c。所以在你的测试台上,你正在运行类似于我上一个命令的东西。但是在您的工作容器中,您很可能只使用一个命令运行 bash -c 并且看起来 bash 变得足够聪明,可以有效地执行 exec。并且可能在生成僵尸的工作容器中,bash 实际上并不是 PID 1,这与您的预期相反。

也许您可以在您现有的工作容器中 ps -ef 并验证我的猜测是否正确。

关于bash - 如何在 docker 中使用 bash 作为 PID1 重现僵尸进程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37022611/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com