Cómo terminar un subproceso de Python iniciado con shell=True

Resuelto user175259 asked hace 13 años • 11 respuestas

Estoy lanzando un subproceso con el siguiente comando:

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

Sin embargo, cuando intento matar usando:

p.terminate()

o

p.kill()

El comando sigue ejecutándose en segundo plano, por lo que me preguntaba cómo puedo finalizar el proceso.

Tenga en cuenta que cuando ejecuto el comando con:

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

Termina exitosamente al emitir el archivo p.terminate().

user175259 avatar Jan 25 '11 10:01 user175259
Aceptado

Utilice un grupo de procesos para permitir el envío de una señal a todos los procesos de los grupos. Para eso, debe adjuntar una identificación de sesión al proceso principal de los procesos generados/secundarios, que es un shell en su caso. Esto lo convertirá en el líder del grupo de los procesos. Ahora, cuando se envía una señal al líder del grupo de procesos, se transmite a todos los procesos secundarios de este grupo.

Aquí está el código:

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
mouad avatar Jan 25 '2011 09:01 mouad
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
p.kill()

p.kill()termina matando el proceso de shell y cmdtodavía se está ejecutando.

Encontré una solución conveniente para esto:

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

Esto hará que cmd herede el proceso del shell, en lugar de que el shell inicie un proceso hijo, que no se elimina. p.pidEntonces será la identificación de su proceso cmd.

p.kill()Deberia trabajar.

Aunque no sé qué efecto tendrá esto en tu pipa.

Bryant Hansen avatar Oct 30 '2012 16:10 Bryant Hansen

Si puedes usar psutil , entonces esto funciona perfectamente:

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)
Jovik avatar Aug 05 '2014 09:08 Jovik

podría hacerlo usando

from subprocess import Popen

process = Popen(command, shell=True)
Popen("TASKKILL /F /PID {pid} /T".format(pid=process.pid))

Mató el cmd.exeprograma y el programa para el que di el comando.

(En Windows)

SPratap avatar Jul 12 '2013 12:07 SPratap

Cuando shell=Trueel shell es el proceso hijo y los comandos son sus hijos. Entonces cualquiera SIGTERMo SIGKILLmatará el shell pero no sus procesos secundarios, y no recuerdo una buena manera de hacerlo. La mejor manera que se me ocurre es usar shell=False; de lo contrario, cuando finalice el proceso de shell principal, dejará un proceso de shell inactivo.

Sai Venkat avatar Jan 25 '2011 04:01 Sai Venkat