[PYTHON] 파이썬 : 부모 프로세스가 죽으면 어떻게 자식 프로세스를 죽일 수 있습니까?)
PYTHON파이썬 : 부모 프로세스가 죽으면 어떻게 자식 프로세스를 죽일 수 있습니까?)
자식 프로세스가 시작됩니다.
subprocess.Popen(arg)
부모가 비정상적으로 종료 될 때 죽는 것을 보장 할 수있는 방법이 있습니까? Windows와 Linux에서 모두 작동해야합니다. Linux 용 솔루션에 대해 알고 있습니다.
편집하다:
프로세스를 시작하는 다른 방법을 사용하여 솔루션이 존재하는 경우 하위 프로세스로 하위 프로세스 시작 요구 사항을 완화 할 수 있습니다.
해결법
-
==============================
1.Heh, 나는 단지 이것을 나 자신으로 어제 연구하고 있었다! 자녀 프로그램을 변경할 수 없다고 가정합니다.
Heh, 나는 단지 이것을 나 자신으로 어제 연구하고 있었다! 자녀 프로그램을 변경할 수 없다고 가정합니다.
리눅스에서는 prctl (PR_SET_PDEATHSIG, ...)만이 유일하게 신뢰할 수있는 선택 일 것이다. (만약 자식 프로세스가 반드시 죽어야한다면, SIGTERM 대신에 SIGKILL로 시그널을 설정하는 것이 좋을 것이다. 링크 된 코드는 SIGTERM을 사용하지만 자식은 원하는 경우 SIGTERM을 무시할 수있는 옵션을 가지고있다. )
Windows에서 가장 신뢰할 수있는 옵션은 Job 객체를 사용하는 것입니다. 아이디어는 "작업"(프로세스의 컨테이너 종류)을 만든 다음 하위 프로세스를 작업에 배치하고 "아무도이 작업에 '핸들'을 보유하지 않을 때 마법 옵션을 설정한다는 것입니다 그런 다음 그 안에있는 프로세스를 종료하십시오. " 기본적으로 작업에 대한 유일한 '처리'는 상위 프로세스가 보유하고있는 프로세스이며, 상위 프로세스가 종료되면 OS는 모든 핸들을 닫고 그 다음에 열린 핸들이 없다는 것을 알게됩니다 작업. 그러면 요청에 따라 자식을 죽입니다. (자식 프로세스가 여러 개인 경우 모두 동일한 작업에 할당 할 수 있습니다.)이 응답에는 win32api 모듈을 사용하여이를 수행하는 샘플 코드가 있습니다. 이 코드는 Subprocess.Popen 대신 CreateProcess를 사용하여 자식을 시작합니다. 그 이유는 생성 된 자식에 대해 "프로세스 핸들"을 가져와야하기 때문에 CreateProcess는 기본적으로이를 반환합니다. subprocess.Popen을 오히려 사용하고 싶다면, 그 대답에서 Subprocess.Popen과 OpenProcess를 사용하는 코드의 (테스트받지 않은) 사본을 CreateProcess 대신 사용하십시오 :
import subprocess import win32api import win32con import win32job hJob = win32job.CreateJobObject(None, "") extended_info = win32job.QueryInformationJobObject(hJob, win32job.JobObjectExtendedLimitInformation) extended_info['BasicLimitInformation']['LimitFlags'] = win32job.JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE win32job.SetInformationJobObject(hJob, win32job.JobObjectExtendedLimitInformation, extended_info) child = subprocess.Popen(...) # Convert process id to process handle: perms = win32con.PROCESS_TERMINATE | win32con.PROCESS_SET_QUOTA hProcess = win32api.OpenProcess(perms, False, child.pid) win32job.AssignProcessToJobObject(hJob, hProcess)
엄밀히 말하면, Popen과 OpenProcess 호출 사이에서 아이가 죽는 경우 작은 경쟁 조건이 있습니다. 걱정할 것인지 결정할 수 있습니다.
작업 개체를 사용할 때의 한 가지 단점은 Vista 또는 Win7에서 실행할 때 프로그램이 Windows 셸에서 (즉, 아이콘을 클릭하여) 실행되면 작업 개체가 이미 할당되어 있고 새 작업 개체가 실패합니다. Win8은 이것을 수정합니다 (작업 개체를 중첩 할 수있게 함). 또는 명령 줄에서 프로그램을 실행하면 문제가 없습니다.
자식을 수정할 수 있다면 (예 : 다중 처리를 사용할 때와 같이) 가장 좋은 방법은 부모의 PID를 자식에게 전달하는 것입니다 (예 : 명령 줄 인수 또는 args = multiprocessing.Process 인수). 그리고:
POSIX에서 : os.getppid ()를 가끔씩 호출하는 자식에 스레드를 생성하십시오. 반환 값이 부모로부터 전달 된 pid와 일치하지 않으면 os._exit ()를 호출하십시오. (이 접근법은 OS X을 포함한 모든 유닉스에 이식 가능하지만 prctl 트릭은 리눅스에만 한정되어있다.)
Windows의 경우 : OpenProcess 및 os.waitpid를 사용하는 하위 스레드를 생성합니다. ctypes 사용 예제 :
from ctypes import WinDLL, WinError from ctypes.wintypes import DWORD, BOOL, HANDLE # Magic value from http://msdn.microsoft.com/en-us/library/ms684880.aspx SYNCHRONIZE = 0x00100000 kernel32 = WinDLL("kernel32.dll") kernel32.OpenProcess.argtypes = (DWORD, BOOL, DWORD) kernel32.OpenProcess.restype = HANDLE parent_handle = kernel32.OpenProcess(SYNCHRONIZE, False, parent_pid) # Block until parent exits os.waitpid(parent_handle, 0) os._exit(0)
이렇게하면 내가 언급 한 작업 개체의 가능한 문제를 피할 수 있습니다.
정말 확실하게 알고 싶다면이 모든 솔루션을 결합 할 수 있습니다.
희망이 도움이됩니다!
-
==============================
2.Popen 객체는 terminate 및 kill 메소드를 제공합니다.
Popen 객체는 terminate 및 kill 메소드를 제공합니다.
https://docs.python.org/2/library/subprocess.html#subprocess.Popen.terminate
이것들은 당신을 위해 SIGTERM과 SIGKILL 시그널을 보낸다. 아래와 비슷한 것을 할 수 있습니다 :
from subprocess import Popen p = None try: p = Popen(arg) # some code here except Exception as ex: print 'Parent program has exited with the below error:\n{0}'.format(ex) if p: p.terminate()
최신 정보:
당신은 맞습니다 - 위의 코드는 하드 충돌이나 프로세스를 죽이는 사람을 보호하지 못합니다. 이 경우 클래스에서 하위 프로세스를 래핑하고 폴링 모델을 사용하여 부모 프로세스를 볼 수 있습니다. psutil은 비표준임을 유의하십시오.
import os import psutil from multiprocessing import Process from time import sleep class MyProcessAbstraction(object): def __init__(self, parent_pid, command): """ @type parent_pid: int @type command: str """ self._child = None self._cmd = command self._parent = psutil.Process(pid=parent_pid) def run_child(self): """ Start a child process by running self._cmd. Wait until the parent process (self._parent) has died, then kill the child. """ print '---- Running command: "%s" ----' % self._cmd self._child = psutil.Popen(self._cmd) try: while self._parent.status == psutil.STATUS_RUNNING: sleep(1) except psutil.NoSuchProcess: pass finally: print '---- Terminating child PID %s ----' % self._child.pid self._child.terminate() if __name__ == "__main__": parent = os.getpid() child = MyProcessAbstraction(parent, 'ping -t localhost') child_proc = Process(target=child.run_child) child_proc.daemon = True child_proc.start() print '---- Try killing PID: %s ----' % parent while True: sleep(1)
이 예제에서는 영원히 실행될 '핑 -t 로컬 호스트'b / c를 실행합니다. 상위 프로세스를 종료하면 하위 프로세스 (ping 명령)도 종료됩니다.
from https://stackoverflow.com/questions/23434842/python-how-to-kill-child-processes-when-parent-dies by cc-by-sa and MIT license
'PYTHON' 카테고리의 다른 글
[PYTHON] Pandas to_html ()은 문자열 내용을 자릅니다. (0) | 2018.10.05 |
---|---|
[PYTHON] OS X에서의 Python 및 OpenSSL 버전 참조 문제 (0) | 2018.10.05 |
[PYTHON] 파이썬 3.3에서 수율과 함께 생성기에서 반환 (0) | 2018.10.05 |
[PYTHON] 파이썬 할당을 오버로드 할 수 있습니까? (0) | 2018.10.05 |
[PYTHON] 곱셈 (*)을 사용하여 하위 목록 생성 예기치 않은 동작 [복제] (0) | 2018.10.05 |