经验证,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!