python无法使用process.terminate终止进程

时间:2014-04-22 19:38:34

标签: python

我有一个python代码如下:

import threading
import time
import subprocess, os, sys, psutil, signal
from signal import SIGKILL

def processing():
    global p_2
    global subp_2
    .
    .
    .
    if condition1: #loop again
          threading.Timer(10,processing).start()
    if condition2:
          signal.signal(signal.SIGINT, signal_handler)
          #signal.signal(signal.SIGTERM, signal_handler)
          subp_2.terminate()   
          #os.kill(subp_2.pid, 0)
          #subp_2.kill()            
          print " Status p_2: ", p_2.status

def signal_handler(signal, frame):
    print('Exiting')
    sys.exit(0)

def function():
    global p_1
    global subp_1
    .
    .
    .
    if condition1: #loop again
          threading.Timer(5,function).start()

    if condition2:

          signal.signal(signal.SIGINT, signal_handler)
          #signal.signal(signal.SIGTERM, signal_handler)
          subp_1.terminate()   
          #os.kill(subp_1.pid, 0)
          #subp_1.kill()            
          print " Status p_1: ", p_1.status
          threading.Timer(10,processing).start()  
          subp_2 =  subprocess.Popen('./myScript2.sh %s %s' % (arg0, arg1), shell=True)
          p_2 = psutil.Process(subp_2.pid)

if __name__ == '__main__':
          global p_1
          global subp_1 
          .
          .
          .
          subp_1 = subprocess.Popen(["/.../myScript1.sh"],  shell=True)
          p_1 = psutil.Process(subp_1.pid)
          threading.Timer(5,function).start()

我无法杀死进程subp_1和subp_2。无论我尝试了什么:.terminate(),. kill()或os.kill()我仍在运行进程状态。有谁能告诉我,我错过了什么?任何提示都表示赞赏。

1 个答案:

答案 0 :(得分:4)

使用shell=True时,首先会生成一个运行shell的子进程。然后shell生成一个运行myScript2.sh的子进程。可以终止运行shell的子进程,而不终止myScript2.sh子进程。

如果您可以避免使用shell=True,那么这将是避免此问题的一种方法。如果使用用户输入来形成命令,则绝对应该避免使用shell=True,因为它是security risk

在Unix上,默认情况下,subprocess.Popen生成的子进程 a session leader。向会话负责人发送信号时,会将其传播到具有相同会话ID的所有进程。因此,要让shell将SIGTERM传递给myScript2.sh,请将shell作为会话负责人。

对于Python版本< 3.2在Unix上,可以通过让she​​ll进程运行os.setsid()

来完成
import os
subp_2 =  subprocess.Popen('./myScript2.sh %s %s' % (arg0, arg1), 
                           shell=True, 
                           preexec_fn=os.setsid)

# To send SIGTERM to the process group:
os.killpg(subp_2.pid, signal.SIGTERM)

对于Unix版本的Python版本> = 3.2,将start_new_session=True传递给Popen

对于Windows,请参阅J.F. Sebastian's solution