[python] shell = True로 시작된 파이썬 서브 프로세스를 종료하는 방법

다음 명령으로 하위 프로세스를 시작합니다.

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

그러나 내가 사용하여 죽일 때 :

p.terminate()

또는

p.kill()

명령이 백그라운드에서 계속 실행되므로 실제로 프로세스를 종료하는 방법이 궁금합니다.

내가 명령을 실행할 때 다음에 유의하십시오.

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

을 발행하면 성공적으로 종료됩니다 p.terminate().



답변

그룹의 모든 프로세스에 신호를 보낼 수 있도록 프로세스 그룹을 사용하십시오 . 이를 위해서는 세션 ID를 첨부해야합니다 생성 된 자식 프로세스의 부모 프로세스에 를 프로세스는 쉘입니다. 이것은 프로세스의 그룹 리더가 될 것입니다. 이제 신호가 프로세스 그룹 리더에게 전송되면이 그룹의 모든 하위 프로세스로 전송됩니다.

코드는 다음과 같습니다.

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


답변

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

p.kill() 쉘 프로세스를 종료하고 cmd 여전히 실행 중입니다.

나는 이것을 통해 편리한 수정을 발견했다.

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

이로 인해 쉘이 자식 프로세스를 시작하는 대신 cmd가 쉘 프로세스를 상속하게되는데이 프로세스는 종료되지 않습니다. p.pid그러면 cmd 프로세스의 ID가됩니다.

p.kill() 작동해야합니다.

그래도 이것이 파이프에 어떤 영향을 미칠지 모르겠습니다.


답변

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)


답변

나는 그것을 사용하여 그것을 할 수있다

from subprocess import Popen

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

그것은 cmd.exe내가 명령을 준 프로그램과 프로그램을 죽였습니다 .

(Windows에서)


답변

shell=True쉘이 자식 프로세스이며, 명령은 그 아이입니다. 어떤 그래서 SIGTERMSIGKILL자식 프로세스 쉘을 죽일 수 있지만, 나는 그것을 할 수있는 좋은 방법을 기억하지 않습니다. 내가 생각할 수있는 가장 좋은 방법은을 사용하는 것입니다 shell=False. 그렇지 않으면 부모 셸 프로세스를 종료하면 사용되지 않는 셸 프로세스가 남습니다.


답변

이 답변 중 어느 것도 나를 위해 일하지 않았으므로 Im은 작동 한 코드를 남겨 둡니다. 필자의 경우 프로세스를 종료 .kill()하고 .poll()리턴 코드를 얻은 후에도 프로세스가 종료되지 않았습니다.

subprocess.Popen 설명서에 따라 :

“… 제대로 작동하는 응용 프로그램을 올바르게 정리하려면 자식 프로세스를 종료하고 통신을 완료해야합니다 …”

proc = subprocess.Popen(...)
try:
    outs, errs = proc.communicate(timeout=15)
except TimeoutExpired:
    proc.kill()
    outs, errs = proc.communicate()

내 경우에는 proc.communicate()전화를 한 후에 실종되었습니다 proc.kill(). 이것은 프로세스 stdin, stdout …을 정리하고 프로세스를 종료합니다.


답변

Sai가 말했듯이 쉘은 자식이므로 신호가 차단됩니다. 내가 찾은 가장 좋은 방법은 shell = False를 사용하고 shlex를 사용하여 명령 줄을 분할하는 것입니다.

if isinstance(command, unicode):
    cmd = command.encode('utf8')
args = shlex.split(cmd)

p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

그러면 p.kill () 및 p.terminate ()가 예상대로 작동합니다.