在Python中使用subprocess终止子进程的子进程

1 投票
2 回答
595 浏览
提问于 2025-04-17 12:12

Python有没有办法找到通过subprocess创建的子进程的子进程,这样我就可以正确地结束它们?如果没有,确保子进程的子进程被结束的好方法是什么?

2 个回答

5

以下内容仅适用于Unix系统:

在子进程中调用 os.setsid() 会让这个子进程成为一个新会话的会话领导者,同时也是一个新 进程组 的领导者。如果你向这个进程组发送一个SIGTERM信号,它会把这个信号发送给所有由这个子进程启动的子进程。

你可以通过 subprocess.Popen(..., preexec_fn=os.setsid) 来实现这个功能。例如:

import signal
import os
import subprocess
import time
PIPE = subprocess.PIPE
proc = subprocess.Popen('ls -laR /', shell=True,
                        preexec_fn=os.setsid,
                        stdout=PIPE, stderr=PIPE)
time.sleep(2)
os.killpg(proc.pid, signal.SIGTERM)

运行这个代码不会有任何输出,但你可以用 ps ax 命令查看,发现子进程和它启动的 ls -laR 都已经被终止了。

但是如果你把

preexec_fn=os.setsid

注释掉,那么用 ps ax 查看时,你会看到类似下面的内容:

% ps ax | grep "ls -la"
 5409 pts/3    S      0:00 /bin/sh -c ls -laR /
 5410 pts/3    R      0:05 ls -laR /

所以如果没有 os.setsidls -laR 和启动它的shell仍然在运行。记得要把它们杀掉:

% kill 5409
% kill 5410
1

这事儿不算简单,不过如果你的应用是在Linux系统上运行的,你可以通过查看/proc这个文件系统,来列出所有的进程ID(PID),这些进程的父进程ID(PPID)和你的小进程是一样的。

撰写回答