码头工人中的终止进程离开内核线程



我正在试验Docker并解决了我的大部分问题,但无法解决这个问题。

我有一个python应用程序,可以定期在docker内打开vpn(通过openvpn客户端(,做一些事情,然后会做

os.system("pkill -f openvpn")
#os.system("killall openvpn")

我已经尝试了这两种方法,并且在独立系统上都可以正常工作,但是在 docker 中,每次杀死 openvpn 恶魔时,它们都会留下内核线程(?

Openvpn 客户端在脚本中是这样调用的:

os.system("/usr/sbin/openvpn --daemon --config " + config_file)

但是每次它被杀的ps都会得到一个[openvpn]

/app # ps auxf
PID   USER     TIME  COMMAND
1 root      0:01 python app.py
9 root      0:00 [openvpn]
10 root      0:00 [openvpn]
16 root      0:00 sh
41 root      0:00 [openvpn]
42 root      0:00 [openvpn]
57 root      0:00 [openvpn]
58 root      0:00 [openvpn]
75 root      0:00 [openvpn]
76 root      0:00 [openvpn]
89 root      0:00 [openvpn]
90 root      0:00 [openvpn]
106 root      0:00 [openvpn]
107 root      0:00 [openvpn]
123 root      0:00 [openvpn]
124 root      0:00 [openvpn]
137 root      0:00 [openvpn]
138 root      0:00 /usr/sbin/openvpn --daemon --config /etc/openvpn/VPNarea/Poland-Warsaw.ovpn
145 root      0:00 ps auxf

为什么会这样?或者如何预防它?

您正在泄漏僵尸进程。

在 Docker 容器内运行时,进程的 ID 为 1。 这意味着,如果容器内的某些东西被杀死,并且它的父进程消失了(例如,因为它完成了双分叉成为守护进程(,您的进程将成为其新的父进程,并且您负责等待(2(它。 当你不这样做时,你会得到这样的僵尸进程。

一个直接的答案可能是在你发出"杀戮"后os.waitpid(-1, 0)。 这将导致您等待下一个退出的操作并进行所需的清理。

不过,不要尝试如此间接地进行此清理会更干净。 您可以使用subprocess.Popen()来创建进程,而不是将子进程作为守护程序启动并在以后尝试清理。 您可以让进程"在前台"运行,但不能阻止它在 Python 进程中完成。 那看起来像

vpn = subprocess.Popen(["/usr/sbin/openvpn", "--config", config_file])
...
vpn.kill()
vpn.wait()

如果你能把事情分开,让这两个项目在单独的容器中运行,那就更好了;那么你就可以避免这个管理问题。

(...config_file = "/dev/null; cat /etc/shadow"时会发生什么? 如果可能的话,尽量避免使用像os.system()这样的字符串形式的命令。

最新更新