如何通过PID连接已启动的Python子进程并获取其标准输出?
如何通过PID获取已启动进程的标准输出?
首先提一句,你当前的nmap命令参数有问题:['nmap', '-', '-oX', '192.168.19.159']里的-是无效参数,应该替换成实际的扫描参数(比如-sS),不过这不是核心问题。
回到你的需求:已经启动的进程的标准输出,默认情况下无法被外部Python脚本直接获取,尤其是在Windows环境下(你用了cmd的tasklist,推测是Windows),进程的IO句柄是私有资源,除非创建时特意做了可继承配置或者预先用IPC机制规划了输出路径。
下面分两种场景给你解决方案:
场景1:还能重新启动目标进程
这是最稳妥的方案,启动时直接把stdout定向到临时文件或者命名管道,后续脚本直接读取即可:
临时文件方案
import subprocess import tempfile # 创建临时文件存储输出(delete=False避免进程未结束就被删除) with tempfile.NamedTemporaryFile(mode='w+', encoding='utf-8', delete=False) as temp_out: # 修正后的nmap命令,把XML输出打印到stdout再写入临时文件 p = subprocess.Popen( ['nmap', '-sS', '192.168.19.159', '-oX', '-'], stdout=temp_out ) temp_path = temp_out.name # 后续独立脚本读取这个临时文件 with open(temp_path, 'r', encoding='utf-8') as f: nmap_output = f.read() print(nmap_output)
命名管道方案(实时读取)
如果需要实时获取输出,可以用Windows的命名管道:
# 启动进程的脚本 import subprocess import win32pipe import win32file # 创建命名管道 pipe_name = r'\\.\pipe\nmap_output' pipe_handle = win32pipe.CreateNamedPipe( pipe_name, win32pipe.PIPE_ACCESS_OUTBOUND, win32pipe.PIPE_TYPE_MESSAGE | win32pipe.PIPE_WAIT, 1, 65536, 65536, 0, None ) # 启动nmap,把stdout定向到管道 subprocess.Popen( ['nmap', '-sS', '192.168.19.159', '-oX', '-'], stdout=pipe_handle ) # 后续读取脚本 def read_nmap_pipe(pipe_name): handle = win32file.CreateFile( pipe_name, win32file.GENERIC_READ, 0, None, win32file.OPEN_EXISTING, 0, None ) while True: try: data = win32file.ReadFile(handle, 4096) print(data[1].decode('utf-8'), end='') except: break read_nmap_pipe(r'\\.\pipe\nmap_output')
场景2:进程已经启动,无法重启
这种情况只能尝试通过Windows API获取进程的stdout句柄,需要用pywin32库,成功率不高,因为依赖句柄权限和原进程的配置:
- 先安装依赖:
pip install pywin32 - 编写读取脚本:
import win32api import win32process import win32file import win32con def read_process_stdout(pid): try: # 打开目标进程(需要足够权限) proc_handle = win32api.OpenProcess(win32con.PROCESS_ALL_ACCESS, False, pid) # 获取标准输出句柄 stdout_handle = win32process.GetStdHandle(proc_handle, win32process.STD_OUTPUT_HANDLE) # 读取输出缓冲区 _, output_bytes = win32file.ReadFile(stdout_handle, 4096) return output_bytes.decode('utf-8', errors='ignore') except Exception as e: return f"读取失败: {str(e)}" # 替换成你的nmap进程PID target_pid = 12345 print(read_process_stdout(target_pid))
注意事项
- 如果原进程的stdout是控制台窗口,读取到的是控制台缓冲区内容,可能包含多余的控制台输出
- 权限不足会直接报错,需要以管理员身份运行脚本
- 如果原进程创建时没有设置stdout句柄可继承,这个方法会失败
为什么psutil/subprocess解决不了?
subprocess只能管理自己创建的进程,没有接口连接外部已启动的进程psutil可以获取进程的基本信息、内存/CPU占用,但无法直接读取外部进程的IO流——这涉及到系统级的句柄权限隔离,不是库能直接解决的问题
内容的提问来源于stack exchange,提问作者SALAVOZ
相关产品推荐
相关产品推荐

