经验证,subprocess自带的kill和terminate函数都不能完全杀掉启动的所有子进程
此时需要借助os的killpg来完成击杀
以判断一个ping命令是否超时,若超时则杀掉进程组为例
要注意的是:
1.这里的subprocess启动的会是一个进程组,有调用ping命令的sh命令,还有ping命令本身,至少会存在两个进程,所以需要将他们都杀掉
解决:通过进程id找到进程组id,os.getpgid(p.id),然后用killpg击杀整个组
2.subprocess的子进程和python脚本处于同一进程组,如果直接通过killpg杀掉整个进程组,会导致整个python脚本被杀掉
解决:另起炉灶,subprocess.Popen中,把start_new_session选项设为True,则subprocess启动的进程不会与python脚本公用同一进程组
借助Timer计时器,用以设置超时时间,以及延时执行kill命令
上代码!
#using os && signal to make sure all subprocess was killed import os import signal #subprocess to run shell command import subprocess #using Timer to control command run time, or start time (unit = s) from threading import Timer #[def] kill process def kill_command(p): os.killpg(os.getpgid(p.pid),signal.SIGTERM) #[fucdef] kill subprocess when (ping) timeout #[usedef] disconnect this robot and continue try connect other robots when connect timeout def execute_command_popen(command,timeout): # run shell command p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE,shell=True,start_new_session=True) # set timer to kill process timer = Timer(timeout, kill_command,[p]) try: timer.start() stdout,stderr = p.communicate() return_code = p.returncode print(return_code) print(stdout) except Exception as ex: print(ex) finally: timer.cancel() execute_command_popen('ping xxx.xxx.xxx.xxx -c4', 20) print("continue!")
return_code返回值:
0,表示执行成功;
负数,代表执行有误或中断;
None,表示进程仍未执行完。
最后打印一个continue!为了观测出python进程是否被整个杀死,我们希望只杀掉所有subprocess进程而保留python进程。
正确的情况下,若规定超时时间内,ping指令已经执行成功,则会打印出0和ping命令产生的log和最后的continue!
,ping指令仍未执行成功,则会打印出负数和空log和最后的continue!