W systemie Windows: subprocess.Popen.terminate
dzwoni do win32: TerminalProcess
. Jednak zachowanie, które widzę, to to, że proces potomny procesu, który próbuję zakończyć, nadal działa. Dlaczego? Jak mogę zabezpieczyć wszystkie procesy potomne rozpoczęte przez proces?podproces: usuwanie procesów podrzędnych w systemie Windows
Odpowiedz
Korzystając 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)
Ten kod wygląda na to, że zabije tylko dzieci pierwszego poziomu, a nie wnuki itp. Może to być problem, jeśli uruchamiasz narzędzia do budowania lub pliki .bat/.cmd przy pomocy cmd.exe.Chyba, że get_children() oznacza również wnuki? – Macke
Dokładnie. Aby włączyć wnuki, powinieneś określić opcję "rekursywną", tak jak w parent.get_children (rekursywna = prawda). –
To stara odpowiedź, ale dokładnie to, czego szukałem - międzyplatformowy sposób zabijania wszystkich procesów podrzędnych. Wszystkie inne odpowiedzi, które pojawiły się w Google, nie pozwalają na to. Dziękuję za psutil! – Gilead
Trudno to zrobić. System Windows faktycznie nie przechowuje drzewa procesów w przestrzeni procesu. Nie można też zakończyć procesu i określić, że dzieci powinny także umrzeć.
Jednym ze sposobów jest użycie taskkill i nakazanie, aby zwinął całe drzewo.
Innym sposobem na to (zakładając, że jesteś tarła proces najwyższego poziomu) jest użycie modułu, który został opracowany z tego typu rzeczy na uwadze: http://benjamin.smedbergs.us/blog/tag/killableprocess/
Aby to zrobić rodzajowo dla siebie , musisz poświęcić trochę czasu na budowanie listy wstecz. Oznacza to, że proces przechowuje wskaźniki do PARENT, ale rodzice wydają się nie przechowywać informacji o dzieciach.
Musisz więc przyjrzeć się wszystkim procesom w systemie (co naprawdę nie jest takie trudne), a następnie samodzielnie połączyć kropki, patrząc na pole procesu nadrzędnego. Następnie wybierasz drzewo, które cię interesuje i wszystko idziesz, zabijając kolejno każdy węzeł, jeden po drugim.
Należy pamiętać, że system Windows nie aktualizuje wskaźnika rodzica dziecka, gdy rodzic umiera, dlatego w drzewie mogą występować przerwy. Nie jestem świadomy niczego, co możesz z tym zrobić.
umieścić dzieci w NT Job object, można zabić wszystkie dzieci
Obiekty zadania wydają się być właściwym sposobem podejścia do tego problemu; szkoda, że nie jest to zintegrowane z modułem podprocesu. –
Korzystając taskkill
z flagą /T
p = subprocess.Popen(...)
<wait>
subprocess.call(['taskkill', '/F', '/T', '/PID', str(p.pid)])
Flagi do taskkill ma następujące dokumenty:
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.
Albo chodzić drzewo procesów za pomocą comtypes i 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)
Dziękuję za to. – Speakeasys
Oto przykładowy kod dla metody obiektu zadania, ale zamiast subprocess
używa 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: wydaje się najbardziej niezawodnym rozwiązaniem, które działa, nawet jeśli proces nadrzędny ulegnie awarii. Oto [wyjaśnienie, jak to działa] (http://stackoverflow.com/a/23587108/4279) – jfs
miałem ten sam problem i po prostu zabijanie za pomocą polecenia Windows z opcją zabijania dzieci "/ 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)
Próbowałem zabić proces kompilacji Gradle rozpoczynam z 'subprocess.Popen()'. Proste 'process.terminate()' lub 'process.kill()' nie działały na Windows 7, podobnie jak opcja 'psutils' powyżej, ale tak właśnie było. –
- 1. Zakończyć podproces w systemie Windows, odmowa dostępu
- 2. Wątki/Porównanie procesów w systemie Linux/Windows
- 3. Jak zabić drzewo procesów w systemie Windows
- 4. Jak wyświetlić listę wszystkich procesów działających w systemie Windows?
- 5. Jak obliczyć wykorzystanie CPU procesu i wszystkich jego procesów podrzędnych w systemie Linux?
- 6. Usuwanie plików według typu w Pythonie w systemie Windows
- 7. Usuwanie wszystkich widoków podrzędnych z widoku
- 8. Edytowanie/usuwanie danych Exif Image w systemie Windows Phone
- 9. Jak oczyścić procesów podrzędnych na child_process.spawn() in node.js
- 10. Jak używać fork() do tworzenia tylko 2 procesów podrzędnych?
- 11. Podproces Pythona równolegle
- 12. Uruchamianie zdalnych procesów w sieci Windows
- 13. Wyświetl listę procesów w systemie Windows w sposób bezpieczny dla zestawów znaków
- 14. Tworzenie (zadania równoległe) w systemie Windows
- 15. CouchDB w systemie Windows?
- 16. Czasomierze w systemie Windows
- 17. Podproces Python wprowadza spacje
- 18. Jak uzyskać uruchamianie aplikacji w systemie Windows?
- 19. GCC w systemie Windows - Bash w systemie Ubuntu w systemie Windows (WSL), CygWin, MinGW
- 20. Czy mogę używać oczekiwać w systemie Windows bez instalowania cygwin?
- 21. rurociągów w powłoce poprzez moduł Pythona podproces
- 22. Usuwanie tylko moich plików w systemie Unix
- 23. Usuwanie historii terminali w systemie Linux
- 24. PHP Usuwanie systemu Windows^M
- 25. Stabilność wskaźnika w systemie Windows Vista
- 26. Wywoływanie pełnej listy procesów systemu Windows w C
- 27. Usuwanie paska tytułu w Windows Forms
- 28. Strptime() odpowiednik w systemie Windows?
- 29. Ograniczenia zasobów w systemie Windows?
- 30. Skonfiguruj Heroku w systemie Windows
Która wersja Pythona i Windowsa? –
Oto 2 opcje 1. Użyj tego exe jako podprocesu, który zabija dla ciebie drzewa procesów: http://www.latenighthacking.com/projects/2002/kill/ 2. Przekształć następujący kod C w Python za pomocą ctypes: http: //stackoverflow.com/questions/1173342/terminate-a-process-tree-c-for-windows – Unknown