自己动手生成一个僵尸进程

创建一个 python 程序

#!/usr/bin/env python3
import subprocess
import time
import os
print(os.getpid())
p = subprocess.Popen(['/bin/sleep', '1'])
time.sleep(1000000)

在这个程序中,主进程会启动一个 sleep 子进程,这个 sleep 在1秒之后就执行结束了,此时,它会进入等待被回收的状态

但是主进程此时进入了 sleep(1000000),在阻塞过程中并没有对子进程进行回收,所以并没有对 子进程 进行回收

6701 主进程,6702 子进程变成了僵尸

也就是说只要满足两个条件就可以轻松的获得一个僵尸进程

  1. 父进程阻塞(sleep)
  2. 子进程结束执行,等待回收

根据以上两种条件,我们尝试一下docker的情况

  1. 我们先创建一个 sleep 的 ubuntu 容器,这个容器的 1号进程是一个 阻塞进程,也就是说它不会回收任何子进程
  2. 我们使用 bash创建了几个 bash 进程

接下来,让我们 kill 27号进程,这样30号进程的父进程就会变成 1号进程(也就是sleep进程)

此时,30号进程的父进程就变成了对它不管不顾的 sleep 进程

因为 27号进程已经被 24号进程回收了,所以宿主机中没有 僵尸进程

我们kill掉 没人管的 30号进程

这样我们就成功的创建了一个僵尸进程

容器内 PID 30,宿主机上 PID 7132

把容器停掉的话,僵尸进程会被宿主机回收

综上所述,当

  1. Docker容器的主进程因为某种原因处于阻塞状态
  2. 主进程创建了一些子进程
  3. 这些 子进程 的 父进程一旦变为 阻塞中的容器主进程 ,它们在运行结束后,将成为无法被回收的 僵尸进程
Send a Message