我正在试验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()
这样的字符串形式的命令。