如何将子进程STDOUT同时输出至日志文件与终端并添加前缀?
当然有完美的实现方案!我来分享两种常用场景下的解决办法,不管你用Python还是Shell脚本都能轻松搞定:
Python 实现方案
如果你用Python管理子进程,subprocess模块就能帮你实现实时捕获、加前缀、双输出的需求。核心思路是捕获子进程的STDOUT,然后同时将格式化后的内容写入日志文件和父进程终端:
import subprocess import sys def monitor_child_process(): # 自定义日志文件路径 log_path = "child_process.log" # 替换成你实际要启动的子进程命令,比如["ping", "google.com"] child_cmd = ["your_child_command", "arg1", "arg2"] # 启动子进程,捕获输出流(合并stderr到stdout方便统一处理) with subprocess.Popen( child_cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, bufsize=1 # 行缓冲,确保实时读取 ) as child_proc: # 打开日志文件准备追加写入 with open(log_path, "a", encoding="utf-8") as log_file: # 逐行读取子进程输出 for line in iter(child_proc.stdout.readline, ""): # 给每行添加[child]前缀,处理换行符避免重复空行 formatted_line = f"[child] {line.rstrip()}\n" # 写入日志并强制刷新缓存(避免内容滞留) log_file.write(formatted_line) log_file.flush() # 输出到父进程终端 sys.stdout.write(formatted_line) sys.stdout.flush() # 输出子进程退出状态 print(f"\n子进程执行完成,退出码: {child_proc.returncode}") if __name__ == "__main__": monitor_child_process()
关键注意事项:
bufsize=1开启行缓冲,保证能实时读取子进程的输出,不会因为系统缓存导致延迟- 如果你的子进程是Python脚本,记得启动时加上
-u参数(比如python -u child_script.py),禁用Python自身的输出缓冲,否则可能无法实时看到内容 stderr=subprocess.STDOUT可选,如果你需要把错误输出也一起捕获处理,可以加上
Shell 脚本实现方案
如果是在Shell环境下,用sed配合tee命令就能快速实现,不需要复杂的代码:
#!/bin/bash # 定义日志文件路径 LOG_FILE="child_output.log" # 启动子进程,给每行加[child]前缀后同时写入日志和终端 # 替换成你的子进程命令即可,比如"ping google.com" your_child_command | sed 's/^/[child] /' | tee -a "$LOG_FILE"
扩展:包含错误输出
如果需要把子进程的STDERR也一起处理(同样加前缀并写入日志),只需要把STDERR重定向到STDOUT:
your_child_command 2>&1 | sed 's/^/[child] /' | tee -a "$LOG_FILE"
关键说明:
sed 's/^/[child] /'是在每一行的开头插入[child]前缀tee -a中的-a表示追加写入日志文件,不加的话会清空原有内容- 同样要注意子进程的缓冲问题,比如某些命令默认会开启块缓冲,此时可以用
stdbuf命令强制改为行缓冲,比如:stdbuf -oL your_child_command 2>&1 | sed 's/^/[child] /' | tee -a "$LOG_FILE"
内容的提问来源于stack exchange,提问作者callum
相关产品推荐
相关产品推荐

