如何终止使用shell=Tru启动的python子进程

2024-04-19 03:38:25 发布

您现在位置:Python中文网/ 问答频道 /正文

我使用以下命令启动子进程:

p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)

但是,当我试图用以下方法杀人时:

p.terminate()

或者

p.kill()

该命令一直在后台运行,所以我想知道如何才能真正终止进程。

请注意,当我使用以下命令运行该命令时:

p = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE)

它在发出p.terminate()时确实成功终止。


Tags: 方法命令cmdtrue进程stdoutshell后台
3条回答

如果您可以使用psutil,那么这非常有效:

import subprocess

import psutil


def kill(proc_pid):
    process = psutil.Process(proc_pid)
    for proc in process.children(recursive=True):
        proc.kill()
    process.kill()


proc = subprocess.Popen(["infinite_app", "param"], shell=True)
try:
    proc.wait(timeout=3)
except subprocess.TimeoutExpired:
    kill(proc.pid)
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
p.kill()

p.kill()结束了shell进程,cmd仍在运行。

我找到了一个方便的方法:

p = subprocess.Popen("exec " + cmd, stdout=subprocess.PIPE, shell=True)

这将导致cmd继承shell进程,而不是让shell启动一个子进程,该子进程不会被杀死。p.pid将是您的cmd进程的id。

p.kill()应该可以。

我不知道这会对你的烟斗有什么影响。

使用process group以便能够向组中的所有进程发送信号。为此,应该将session id附加到派生/子进程的父进程,在您的情况下,父进程是shell。这将使它成为流程的组长。所以现在,当一个信号被发送到进程组长时,它被发送到这个组的所有子进程。

代码如下:

import os
import signal
import subprocess

# The os.setsid() is passed in the argument preexec_fn so
# it's run after the fork() and before  exec() to run the shell.
pro = subprocess.Popen(cmd, stdout=subprocess.PIPE, 
                       shell=True, preexec_fn=os.setsid) 

os.killpg(os.getpgid(pro.pid), signal.SIGTERM)  # Send the signal to all the process groups

相关问题 更多 >