Trên Windows, subprocess.Popen.terminate
gọi số TerminalProcess
của win32. Tuy nhiên, hành vi tôi thấy là quá trình con của quá trình tôi đang cố gắng chấm dứt vẫn đang chạy. Tại sao vậy? Làm thế nào để đảm bảo tất cả các tiến trình con bắt đầu bởi quá trình này bị giết?quy trình con: xóa quy trình con trong Windows
Trả lời
Bằng cách sử dụng 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)
Mã đó trông giống như nó sẽ chỉ giết trẻ em cấp đầu tiên, không phải cháu, vv Có thể là một vấn đề nếu bạn đang khởi chạy công cụ xây dựng hoặc .bat/.cmd tệp với cmd.exe.Trừ khi get_children() có nghĩa là cháu quá? – Macke
Chính xác. Để bao gồm các cháu, bạn nên chỉ định tùy chọn 'đệ quy' như trong parent.get_children (recursive = True) –
Đây là câu trả lời cũ, nhưng đó là chính xác những gì tôi đang tìm kiếm - một cách đa nền tảng để giết tất cả các tiến trình con. Tất cả các câu trả lời khác xuất hiện trên Google đều không thể thực hiện được. Cảm ơn bạn đã cho psutil! – Gilead
Đây là một việc khó làm. Windows không thực sự lưu trữ một cây xử lý trong không gian tiến trình. Cũng không thể chấm dứt một quá trình và chỉ ra rằng đó là trẻ em cũng nên chết.
Một cách xung quanh đó là sử dụng taskkill và yêu cầu nó chặn toàn bộ cây.
Một cách khác để làm điều đó (giả sử rằng bạn đang đẻ trứng quá trình cấp cao nhất) là sử dụng một mô-đun đã được phát triển với các loại điều này trong tâm trí: http://benjamin.smedbergs.us/blog/tag/killableprocess/
Để làm được điều này quát cho chính mình , bạn phải dành thời gian xây dựng danh sách ngược. Đó là, một quá trình lưu trữ con trỏ đến PARENT của nó, nhưng cha mẹ dường như không lưu trữ thông tin về trẻ em.
Vì vậy, bạn phải xem xét tất cả các quy trình trong hệ thống (thực sự không khó), sau đó tự kết nối các dấu chấm bằng cách xem trường quy trình gốc. Sau đó, bạn chọn cây bạn quan tâm và đi bộ toàn bộ điều, giết chết từng nút lần lượt từng cái một.
Lưu ý rằng Windows không cập nhật con trỏ mẹ của con khi cha mẹ chết, vì vậy có thể có khoảng trống trong cây của bạn. Tôi không biết bất cứ điều gì bạn có thể làm về những điều đó.
Đặt trẻ em trong một NT Job object, sau đó bạn có thể giết chết tất cả trẻ em
Các đối tượng công việc có vẻ đúng cách để tiếp cận vấn đề này; quá tệ đến nỗi điều này không được tích hợp với mô-đun subprocess. –
Sử dụng taskkill
với /T
cờ
p = subprocess.Popen(...)
<wait>
subprocess.call(['taskkill', '/F', '/T', '/PID', str(p.pid)])
Cờ để taskkill có các tài liệu sau:
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.
Hoặc đi bộ cây quá trình sử dụng comtypes và 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)
Cảm ơn bạn vì điều này. – Speakeasys
Dưới đây là ví dụ mã cho phương pháp đối tượng công việc, nhưng thay vì subprocess
nó sử dụng 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)
+1: có vẻ như giải pháp mạnh mẽ nhất hoạt động ngay cả khi quá trình gốc bị lỗi. Đây là [giải thích về cách nó hoạt động] (http://stackoverflow.com/a/23587108/4279) – jfs
tôi đã cùng một vấn đề và chỉ cần giết quá trình qua lệnh cửa sổ với tùy chọn giết trẻ em "/ 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)
Tôi đã cố gắng để giết một quá trình xây dựng Gradle bắt đầu với 'subprocess.Popen()'. Một 'process.terminate()' hay 'process.kill()' đơn giản không hoạt động trên WIndows 7, và cả tùy chọn 'psutils' ở trên, nhưng điều này đã làm. –
Phiên bản nào của Python và Windows? –
Dưới đây là 2 tùy chọn 1. Sử dụng exe này như là một tiến trình con mà giết chết các cây xử lý cho bạn: http://www.latenighthacking.com/projects/2002/kill/ 2. Chuyển đổi mã C sau sang Python với ctypes: http: //stackoverflow.com/questions/1173342/terminate-a-process-tree-c-for-windows – Unknown