[PYTHON] 하위 프로세스 : Windows에서 하위 프로세스 삭제
PYTHON하위 프로세스 : Windows에서 하위 프로세스 삭제
Windows에서 subprocess.Popen.terminate는 win32의 TerminalProcess를 호출합니다. 그러나, 내가 보는 행동은 내가 종료하려고하는 프로세스의 자식 프로세스가 여전히 실행 중이다. 왜 그런가요? 프로세스에 의해 시작된 모든 하위 프로세스가 종료되었는지 어떻게 확인합니까?
해결법
-
==============================
1.psutil을 사용하여 :
psutil을 사용하여 :
import psutil, os def kill_proc_tree(pid, including_parent=True): parent = psutil.Process(pid) children = parent.children(recursive=True) for child in children: child.kill() gone, still_alive = psutil.wait_procs(children, timeout=5) if including_parent: parent.kill() parent.wait(5) me = os.getpid() kill_proc_tree(me)
-
==============================
2./ T 플래그와 함께 taskkill 사용
/ T 플래그와 함께 taskkill 사용
p = subprocess.Popen(...) <wait> subprocess.call(['taskkill', '/F', '/T', '/PID', str(p.pid)])
taskkill에 대한 플래그는 다음과 같습니다.
TASKKILL [/S system [/U username [/P [password]]]] { [/FI filter] [/PID processid | /IM imagename] } [/T] [/F] /S system Specifies the remote system to connect to. /U [domain\]user Specifies the user context under which the command should execute. /P [password] Specifies the password for the given user context. Prompts for input if omitted. /FI filter Applies a filter to select a set of tasks. Allows "*" to be used. ex. imagename eq acme* /PID processid Specifies the PID of the process to be terminated. Use TaskList to get the PID. /IM imagename Specifies the image name of the process to be terminated. Wildcard '*' can be used to specify all tasks or image names. /T Terminates the specified process and any child processes which were started by it. /F Specifies to forcefully terminate the process(es). /? Displays this help message.
또는 comtypes와 win32api를 사용하여 프로세스 트리를 살펴보십시오.
def killsubprocesses(parent_pid): '''kill parent and all subprocess using COM/WMI and the win32api''' log = logging.getLogger('killprocesses') try: import comtypes.client except ImportError: log.debug("comtypes not present, not killing subprocesses") return logging.getLogger('comtypes').setLevel(logging.INFO) log.debug('Querying process tree...') # get pid and subprocess pids for all alive processes WMI = comtypes.client.CoGetObject('winmgmts:') processes = WMI.InstancesOf('Win32_Process') subprocess_pids = {} # parent pid -> list of child pids for process in processes: pid = process.Properties_('ProcessID').Value parent = process.Properties_('ParentProcessId').Value log.trace("process %i's parent is: %s" % (pid, parent)) subprocess_pids.setdefault(parent, []).append(pid) subprocess_pids.setdefault(pid, []) # find which we need to kill log.debug('Determining subprocesses for pid %i...' % parent_pid) processes_to_kill = [] parent_processes = [parent_pid] while parent_processes: current_pid = parent_processes.pop() subps = subprocess_pids[current_pid] log.debug("process %i children are: %s" % (current_pid, subps)) parent_processes.extend(subps) processes_to_kill.extend(subps) # kill the subprocess tree if processes_to_kill: log.info('Process pid %i spawned %i subprocesses, terminating them...' % (parent_pid, len(processes_to_kill))) else: log.debug('Process pid %i had no subprocesses.' % parent_pid) import ctypes kernel32 = ctypes.windll.kernel32 for pid in processes_to_kill: hProcess = kernel32.OpenProcess(PROCESS_TERMINATE, FALSE, pid) if not hProcess: log.warning('Unable to open process pid %i for termination' % pid) else: log.debug('Terminating pid %i' % pid) kernel32.TerminateProcess(hProcess, 3) kernel32.CloseHandle(hProcess)
-
==============================
3.이것은 어려운 일입니다. Windows는 실제로 프로세스 공간에 프로세스 트리를 저장하지 않습니다. 또한 프로세스를 종료하고 자식도 죽어야한다고 지정할 수 없습니다.
이것은 어려운 일입니다. Windows는 실제로 프로세스 공간에 프로세스 트리를 저장하지 않습니다. 또한 프로세스를 종료하고 자식도 죽어야한다고 지정할 수 없습니다.
한 가지 방법은 태스크 킬을 사용하여 전체 트리를 해킹하는 것입니다.
이것을 수행하는 다른 방법 (최상위 프로세스를 생성한다고 가정)은 이런 종류의 것을 염두에두고 개발 된 모듈을 사용하는 것입니다. http://benjamin.smedbergs.us/blog/tag/killableprocess/
이를 일반적으로 직접 수행하려면 목록을 거꾸로 작성해야합니다. 즉, 프로세스는 부모의 포인터를 저장하지만 부모는 자식에 대한 정보를 저장하지 않는 것처럼 보입니다.
따라서 시스템의 모든 프로세스 (실제로 그리 어려운 것은 아닙니다)를 살펴본 다음 부모 프로세스 필드를보고 직접 점을 연결해야합니다. 그런 다음 관심있는 트리를 선택하고 모든 것을 걸어 다니면서 각 노드를 하나씩 차례대로 죽이십시오.
부모가 죽으면 Windows는 자식의 부모 포인터를 업데이트하지 않으므로 트리에 간격이있을 수 있습니다. 나는 당신이 그 일들에 대해 할 수있는 어떤 일도 모르고 있습니다.
-
==============================
4.아이들을 NT 작업 객체에 넣으면 모든 자식을 죽일 수 있습니다.
아이들을 NT 작업 객체에 넣으면 모든 자식을 죽일 수 있습니다.
-
==============================
5.다음은 Job 객체 메소드의 예제 코드이지만, 서브 프로세스 대신 win32api.CreateProcess
다음은 Job 객체 메소드의 예제 코드이지만, 서브 프로세스 대신 win32api.CreateProcess
import win32process import win32job startup = win32process.STARTUPINFO() (hProcess, hThread, processId, threadId) = win32process.CreateProcess(None, command, None, None, True, win32process.CREATE_BREAKAWAY_FROM_JOB, None, None, startup) 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) win32job.AssignProcessToJobObject(hJob, hProcess)
-
==============================
6.나는 똑같은 문제가 있었고 윈도우 커맨드를 통해 자식 죽이는 옵션을 가진 프로세스를 죽이는 "/ T"
나는 똑같은 문제가 있었고 윈도우 커맨드를 통해 자식 죽이는 옵션을 가진 프로세스를 죽이는 "/ T"
def kill_command_windows(pid): '''Run command via subprocess''' dev_null = open(os.devnull, 'w') command = ['TASKKILL', '/F', '/T', '/PID', str(pid)] proc = subprocess.Popen(command, stdin=dev_null, stdout=sys.stdout, stderr=sys.stderr)
from https://stackoverflow.com/questions/1230669/subprocess-deleting-child-processes-in-windows by cc-by-sa and MIT license
'PYTHON' 카테고리의 다른 글
[PYTHON] 대화 형 Matplotlib 수치 저장 (0) | 2018.10.04 |
---|---|
[PYTHON] 다중 상속을 가진 부모 클래스 __init__을 호출하는 것이 옳은 방법일까요? (0) | 2018.10.04 |
[PYTHON] 장고 템플릿에서 getattr () 스타일 룩업 수행하기 (0) | 2018.10.04 |
[PYTHON] Selenium을 사용하여 인증서를 처리하는 방법은 무엇입니까? (0) | 2018.10.04 |
[PYTHON] 파이썬 팬더 중복 열 제거 (0) | 2018.10.04 |