如何正确杀死应用程序启动的所有进程?
问题描述:
我们有一个用Python编写的大型应用程序。当我们关闭或中断它时,我们希望干净地杀掉我们的应用程序启动的进程。然而,通过Python代码(例如subprocess.Popen或使用os.system),我们有一个命令甲这将启动子命令另一个乙但命令乙似乎与命令甲无关。命令B的父进程是init进程(使用pid 1)。如何在Python代码中杀死进程B(例如在Ctrl + C之后)?如何正确杀死应用程序启动的所有进程?
例如,我们有两个shell脚本和一个调用这些shell脚本的Python脚本。
第一外壳脚本mycommand1.sh是:
#!/bin/sh
sleep 3600 &
第二壳脚本mycommand2.sh是:
#!/bin/sh
sleep 3600
的Python脚本myscript.py是:
import os
import signal
import subprocess
def launchCommands():
proc1 = subprocess.Popen('./mycommand1.sh', stdout=subprocess.PIPE, shell = True, preexec_fn=os.setsid)
print "the processus 1 has started"
proc2 = subprocess.Popen('./mycommand2.sh', stdout=subprocess.PIPE, shell = True, preexec_fn=os.setsid)
print "the processus 2 has started"
return proc1, proc2
if __name__ == '__main__':
proc1 = None
proc2 = None
try:
proc1, proc2 = launchCommands()
while True:
pass
except KeyboardInterrupt:
print "Ctrl+C received! ..."
print "trying to kill the processus 2"
os.killpg(os.getpgid(proc2.pid), signal.SIGTERM)
print "processus 2 has been killed"
print "trying to kill the processus 1"
os.killpg(os.getpgid(proc1.pid), signal.SIGTERM)
print "processus 1 has been killed"
然后我们执行我们的Python脚本,并在3秒后用Ctrl + C打断它。 这是中断后的输出。
$> python myscript.py
the processus 1 has started
the processus 2 has started
^CCtrl+C received! ...
trying to kill the processus 2
processus 2 has been killed
trying to kill the processus 1
Traceback (most recent call last):
File "myscript.py", line 33, in <module>
os.killpg(os.getpgid(proc1.pid), signal.SIGTERM)
OSError: [Errno 3] No such process
我们显示所有的“睡眠”过程,而与Python脚本执行后(当然,还有就是Python脚本执行之前没有睡眠过程)。
当运行myscript.py命令:
$> ps -ef | grep sleep
501 50700 1 0 2:21 ?? 0:00.00 sleep 3600
501 50701 50699 0 2:21 ?? 0:00.00 sleep 3600
501 50703 410 0 2:21 ttys002 0:00.00 grep sleep
用Ctrl + C中断程序后:
$> ps -ef | grep sleep
501 50700 1 0 2:21 ?? 0:00.00 sleep 3600
501 51025 410 0 2:23 ttys002 0:00.00 grep sleep
正如我们所看到的,我们试图杀死进程1不存在并且父pid为1的一个进程睡眠总是存在。此进程睡眠来自脚本mycommand1.sh的执行。如何正确杀死这个进程睡眠脚本myscript.py(当然,我们不希望杀死所有的睡眠进程)?
答
尝试重写mycommand1.sh
#!/bin/sh
foo(){
cnt=0
while [ $cnt -le 100 ]; do
cnt=$((cnt+1))
echo $0 $cnt
sleep 1
done
}
foo &
和mycommand2.sh
#!/bin/sh
foo(){
cnt=0
while [ $cnt -le 100 ]; do
cnt=$((cnt+1))
echo $0 $cnt
sleep 1
done
}
foo
从myscript.py
删除stdout=subprocess.PIPE
进行检查。
答
我遵循您的所有说明。这里是输出:
$> python myscript.py
1427
the processus 1 has started
1428
the processus 2 has started
./mycommand1.sh 1
./mycommand2.sh 1
./mycommand1.sh 2
./mycommand2.sh 2
^CCtrl+C received! ...
trying to kill the processus 2
processus 2 has been killed
trying to kill the processus 1
Traceback (most recent call last):
File "myscript.py", line 38, in <module>
os.killpg(os.getpgid(proc1.pid), signal.SIGTERM)
OSError: [Errno 3] No such process
$> ./mycommand1.sh 3
./mycommand1.sh 4
./mycommand1.sh 5
./mycommand1.sh 6
./mycommand1.sh 7
./mycommand1.sh 8
./mycommand1.sh 9
在Ctrl + C之后,脚本mycommand1.sh继续运行。
注:1427和1428分别是过程1的我不能重现它的PGID和2
proc1or2 = subprocess.Popen('./mycommand1or2.sh', shell = True, preexec_fn=os.setsid)
print(os.getpgid(proc1or2.pid))
print "the processus 1or2 has started"
。我做了你所描述的一切 – RedEyed
非常感谢你对我的问题的兴趣。我在Mac(macOS Sierra 10.12.3)上做了这些实验,我的Python版本是2.7.13。我已经复制了我在我的问题中编写的所有代码,我刚才在启动python命令(chmod 755 mycommand * .sh)之前为shell脚本添加了权限,并且我很好地重现了这个问题。 –
我在Ubuntu 17上测试它,并且无法重现它。我也在Python 2.7.13上测试了它。 – RedEyed