简体   繁体   English

如何使用 bash 在 docker 容器中获取僵尸进程

[英]How to reap zombie process in docker container with bash

Recently I'm studying dumb-init and if I realized correctly it's trying to:最近我正在研究 哑初始化,如果我正确地意识到它正在尝试:

  1. runs as PID1, acting like a simple init system(reaping zombie processes)作为 PID1 运行,就像一个简单的初始化系统(收获僵尸进程)
  2. signal proxy/forwarding (which bash doesn't do)信号代理/转发(bash 不这样做)

In both here andhere they all mentioned that bash is capable of reaping zombie process so I'm trying to verify this but couldn't make it work.这里这里他们都提到bash能够收获僵尸进程,所以我试图验证这一点,但无法使其工作。

First of all I wrote a simple Go program which spawn 10 zombie process:首先我写了一个简单的 Go 程序,它产生 10 个僵尸进程:

func main() {
    sigs := make(chan os.Signal, 1)

    signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM, syscall.SIGKILL)

    go func() {
        for i := 0; i < 10; i++ {
            sleepCmd := exec.Command("sleep", "1")
            _ = sleepCmd.Start()
        }
    }()

    fmt.Println("awaiting signal")
    sig := <-sigs
    fmt.Println()
    fmt.Printf("received %s, exiting\n", sig.String())
}

build a image for it:为它构建一个图像:

FROM golang:1.15-alpine3.12 as builder

WORKDIR /

COPY . .

RUN go build -o main main.go

FROM alpine:3.12

RUN apk --no-cache --update add dumb-init bash

WORKDIR /
COPY --from=builder /main /
COPY --from=builder /entrypoint.sh /
RUN chmod +x /entrypoint.sh

ENTRYPOINT ["/main"]

and if I run docker run -d <image> it works as expected I can see 10 zombies process in ps :如果我运行docker run -d <image>它按预期工作,我可以在ps中看到 10 个僵尸进程:

vagrant@vagrant:/vagrant/dumb-init$ ps aux | grep sleep
root      4388  0.0  0.0      0     0 ?        Z    13:54   0:00 [sleep] <defunct>
root      4389  0.0  0.0      0     0 ?        Z    13:54   0:00 [sleep] <defunct>
root      4390  0.0  0.0      0     0 ?        Z    13:54   0:00 [sleep] <defunct>
root      4391  0.0  0.0      0     0 ?        Z    13:54   0:00 [sleep] <defunct>
root      4392  0.0  0.0      0     0 ?        Z    13:54   0:00 [sleep] <defunct>
root      4393  0.0  0.0      0     0 ?        Z    13:54   0:00 [sleep] <defunct>
root      4394  0.0  0.0      0     0 ?        Z    13:54   0:00 [sleep] <defunct>
root      4395  0.0  0.0      0     0 ?        Z    13:54   0:00 [sleep] <defunct>
root      4396  0.0  0.0      0     0 ?        Z    13:54   0:00 [sleep] <defunct>
root      4397  0.0  0.0      0     0 ?        Z    13:54   0:00 [sleep] <defunct>

the 2nd step is to verify bash is actually capable of reaping process, so I update my docker image ENTRYPOINT to entrypoint.sh, which just wrap my program with bash:第二步是验证bash是否真的能够收割进程,所以我将我的 docker 图像 ENTRYPOINT 更新为 entrypoint.sh,它只是用 ZD574D4BB40C849961791A6949 包装我的程序:

#!/bin/bash

/clever

if I run ps in the container the zombie processes are still hanging there:如果我在容器中运行ps ,僵尸进程仍然挂在那里:

/ # ps
PID   USER     TIME  COMMAND
    1 root      0:00 {entrypoint.sh} /bin/bash /entrypoint.sh
    7 root      0:00 /clever
   13 root      0:00 [sleep]
   14 root      0:00 [sleep]
   15 root      0:00 [sleep]
   16 root      0:00 [sleep]
   17 root      0:00 [sleep]
   18 root      0:00 [sleep]
   19 root      0:00 [sleep]
   20 root      0:00 [sleep]
   21 root      0:00 [sleep]
   22 root      0:00 [sleep]
   31 root      0:00 /bin/sh
   39 root      0:00 ps

Tried a few other way but still couldn't figure out how to reap the zombie process correctly.尝试了其他一些方法,但仍然无法弄清楚如何正确获取僵尸进程。

thanks for the help.谢谢您的帮助。

I wrote small demo in c that can help to demonstrate that bash had reaped the zombie processes and how it would look like if he had not.我在c中写了一个小演示,它可以帮助证明bash已经收获了僵尸进程,以及如果他没有的话会是什么样子。

First to explain the definition of zombie process.首先解释一下僵尸进程的定义。 The zombie process is a process who had finished the work and generated an exit code.僵尸进程是完成工作并生成退出代码的进程。 The resources are kept by the kernel waiting for the parent to collect the exit code.资源由 kernel 保留,等待父级收集退出代码。

To have zombie, parent needs to ignore the child's exit (don't issue wait and ignore SIGCHLD ).要拥有僵尸,父母需要忽略孩子的退出(不要发出wait并忽略SIGCHLD )。

Reaping the zombies收割僵尸

The following c code is creating two zombie processes.下面的c代码正在创建两个僵尸进程。 One belonging to the main process, and one that belongs to the first child.一个属于主进程,一个属于第一个子进程。

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <pthread.h>
#include <sys/wait.h>
#include <unistd.h>

int main()
{
    printf("Starting Program!\n");

    int pid = fork();
    if (pid == 0)
    {
        pid = fork(); // Create a child zombie
        if (pid == 0) {
            printf("Zombie process %i of the child process\n", getpid());
            exit(10);
        } else {
            printf("Child process %i is running!\n", getpid());
            sleep(10);  // wait 10s
            printf("Child process %i is exiting!\n", getpid());
            exit(0);
        }
    }
    else if (pid > 0)
    {
        pid = fork();
        if (pid == 0) {
            printf("Zombie process %i from the parent process\n", getpid());
        } else {
            printf("Parent process %i...\n", getpid());
            sleep(5);
            printf("Parent process will crash with segmentation failt!\n");
            int* p = 0;
            p = 10;
        }
    }
    else perror("fork()");
    exit(-1);
}

I also created a docker container that will compile the file and the child.我还创建了一个 docker 容器,它将编译文件和子文件。 The whole project is available in following git repository整个项目可在以下 git存储库中获得

After running the build, and the demo, the following printout is shown in the console:运行构建和演示后,控制台中显示以下打印输出:

root@d2d87f4aafbc:/zombie# ./zombie & ps -eaf --forest
[1] 8
Starting Program!
Parent process 8...
Zombie process 11 from the parent process
Child process 10 is running!
Zombie process 12 of the child process
UID          PID    PPID  C STIME TTY          TIME CMD
root           1       0  0 10:43 pts/0    00:00:00 /bin/bash
root           8       1  0 10:43 pts/0    00:00:00 ./zombie
root          10       8  0 10:43 pts/0    00:00:00  \_ ./zombie
root          12      10  0 10:43 pts/0    00:00:00  |   \_ [zombie] <defunct>
root          11       8  0 10:43 pts/0    00:00:00  \_ [zombie] <defunct>
root           9       1  0 10:43 pts/0    00:00:00 ps -eaf --forest
root@d2d87f4aafbc:/zombie# Parent process will crash with segmentation failt!
ps -eaf --forest
UID          PID    PPID  C STIME TTY          TIME CMD
root           1       0  0 10:43 pts/0    00:00:00 /bin/bash
root          10       1  0 10:43 pts/0    00:00:00 ./zombie
root          12      10  0 10:43 pts/0    00:00:00  \_ [zombie] <defunct>
root          13       1  0 10:43 pts/0    00:00:00 ps -eaf --forest
[1]+  Exit 255                ./zombie
root@d2d87f4aafbc:/zombie# Child process 10 is exiting!
ps -eaf --forest
UID          PID    PPID  C STIME TTY          TIME CMD
root           1       0  0 10:43 pts/0    00:00:00 /bin/bash
root          14       1  0 10:43 pts/0    00:00:00 ps -eaf --forest

The main process (PID 8) creates two children.主进程 (PID 8) 创建了两个子进程。

  • A child (PID 10) that will create a zombie child (PID 12) and will sleep for 10 seconds.一个子进程 (PID 10) 将创建一个僵尸子进程 (PID 12) 并将休眠 10 秒。
  • A child that will become zombie (PID 11).一个将成为僵尸的孩子(PID 11)。

After the creation of the processes, the parent process will sleep for 5s and create segmentation fault, leaving the zombies.进程创建完成后,父进程会休眠5s,产生segmentation fault,留下zombies。

When the main process dies, the PID 11 is inherited by bash and it's cleaned up (reaped).当主进程终止时,PID 11 由bash继承并被清理(回收)。 PID 10 is still working (sleeping is a kind of work for a process) he is left alone by bash , since PID 11 had not invoked wait , the PID 12 is still zombie. PID 10 仍在工作(睡眠是进程的一种工作)他被bash ,因为 PID 11 没有调用wait ,所以 PID 12 仍然是僵尸。

After 5 seconds, PID 11 had finished sleeping and exited. 5 秒后,PID 11 完成睡眠并退出。 Bash had reaped and inherited PID 12 after which bash had reaped PID 12 Bash 获得并继承了 PID 12,之后 bash 获得了 PID 12

Leaving zombies离开僵尸

The other c application is just executing the bash as a child process, leaving it to be the PID 1, and he will ignore the zombies.另一个c应用程序只是将bash作为子进程执行,将其保留为 PID 1,他将忽略僵尸。

# docker run -ti --rm test /zombie/ignore
root@b9d49363cb57:/zombie# ./zombie & ps -eaf --forest
[1] 10
Starting Program!
Parent process 10...
Zombie process 13 from the parent process
Child process 12 is running!
Zombie process 14 of the child process
UID          PID    PPID  C STIME TTY          TIME CMD
root           1       0  0 11:18 pts/0    00:00:00 /zombie/ignore
root           7       1  0 11:18 pts/0    00:00:00 sh -c /bin/bash
root           8       7  0 11:18 pts/0    00:00:00  \_ /bin/bash
root          10       8  0 11:18 pts/0    00:00:00      \_ ./zombie
root          12      10  0 11:18 pts/0    00:00:00      |   \_ ./zombie
root          14      12  0 11:18 pts/0    00:00:00      |   |   \_ [zombie] <defunct>
root          13      10  0 11:18 pts/0    00:00:00      |   \_ [zombie] <defunct>
root          11       8  0 11:18 pts/0    00:00:00      \_ ps -eaf --forest
root@b9d49363cb57:/zombie# pParent process will crash with segmentation failt!
ps -eaf --forest
UID          PID    PPID  C STIME TTY          TIME CMD
root           1       0  0 11:18 pts/0    00:00:00 /zombie/ignore
root           7       1  0 11:18 pts/0    00:00:00 sh -c /bin/bash
root           8       7  0 11:18 pts/0    00:00:00  \_ /bin/bash
root          15       8  0 11:18 pts/0    00:00:00      \_ ps -eaf --forest
root          12       1  0 11:18 pts/0    00:00:00 ./zombie
root          14      12  0 11:18 pts/0    00:00:00  \_ [zombie] <defunct>
root          13       1  0 11:18 pts/0    00:00:00 [zombie] <defunct>
[1]+  Exit 255                ./zombie
root@b9d49363cb57:/zombie# Child process 12 is exiting!
ps -eaf --forest
UID          PID    PPID  C STIME TTY          TIME CMD
root           1       0  0 11:18 pts/0    00:00:00 /zombie/ignore
root           7       1  0 11:18 pts/0    00:00:00 sh -c /bin/bash
root           8       7  0 11:18 pts/0    00:00:00  \_ /bin/bash
root          16       8  0 11:18 pts/0    00:00:00      \_ ps -eaf --forest
root          12       1  0 11:18 pts/0    00:00:00 [zombie] <defunct>
root          13       1  0 11:18 pts/0    00:00:00 [zombie] <defunct>
root          14       1  0 11:18 pts/0    00:00:00 [zombie] <defunct>
root@b9d49363cb57:/zombie#

So now, we have 3 zombies left in the system, hanging.所以现在,我们在系统中剩下 3 个僵尸,挂着。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM