Python3运行带管道的命令并将结果实时输出到屏幕的问题咨询
解决方法
核心问题原因
- 缺少
sys模块导入,直接调用sys.stdout会触发名称错误 - 原shell命令中使用
>将输出全部重定向到了文件,进程stdout没有数据流入Python管道,无法读取内容打印 - 代码中调用的
process.buffer属性不存在,运行时会抛出属性错误
修正后可运行代码
import subprocess import sys from datetime import datetime import os # 通用shell命令执行函数:支持带管道的命令,实时打印输出同时写入文件 def run_shell_command(cmd, output_file_path=None): process = subprocess.Popen( cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, # 把标准错误也合并到输出,方便排查问题 bufsize=0 # 关闭缓冲区,保证实时输出 ) # 如果指定了输出文件就打开 output_file = open(output_file_path, 'wb') if output_file_path else None # 逐字节读输出实时打印 for c in iter(lambda: process.stdout.read(1), b''): # 打印到屏幕 sys.stdout.buffer.write(c) sys.stdout.buffer.flush() # 写入文件(如果需要) if output_file: output_file.write(c) output_file.flush() # 等待命令执行完成,返回退出码 return process.wait() # 业务逻辑 currentDateTime = datetime.today().strftime('%Y%m%d_%H%M%S') domain = "tesla.com" waybackurlsDir = "/opt/project/recon/{0}/_waybackurls".format(domain) os.makedirs(waybackurlsDir, exist_ok=True) # 加exist_ok=True避免目录已存在时报错 # 单条命令执行示例(去掉了原命令里的>重定向,改为函数参数指定输出文件) payload = '/usr/bin/echo "{0}" | /root/go-workspace/bin/waybackurls'.format(domain) output_path = f"{waybackurlsDir}/{currentDateTime}_waybackurls.txt" run_shell_command(payload, output_path) # 多条命令顺序执行示例 cmd_list = [ ("echo '第一条命令执行'", "/tmp/cmd1.log"), ("ls -la /opt | grep project", "/tmp/cmd2.log"), ("cat /etc/os-release", None) # 传None就只打印不存文件 ] for cmd, out_path in cmd_list: print(f"\n=== 开始执行命令:{cmd} ===") exit_code = run_shell_command(cmd, out_path) print(f"\n=== 命令执行完成,退出码:{exit_code} ===")
功能说明
- 函数默认合并了标准错误输出到stdout,所有执行日志都会实时打印,方便排查命令执行错误
- 增加了
bufsize=0关闭缓冲区,避免输出堆积延迟打印 - 加了
os.makedirs的exist_ok=True参数,重复运行不会因为目录已存在报错 - 支持批量传入多条命令,会按照顺序挨个执行,前一条执行完成才会运行下一条
- 不需要存输出文件的命令,给第二个参数传
None即可
内容的提问来源于stack exchange,提问作者Keith Smith
相关产品推荐
相关产品推荐

