You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Python脚本中将ansible-playbook命令的STDOUT输出到日志文件?

问题原因

你的Logger类通过替换sys.stdout实现了Python代码中print内容的双输出,但os.system('ansible-playbook test3.yaml')执行的系统命令,其输出是直接通过系统层面的文件描述符写入终端的,不会经过Python的sys.stdout管道,因此日志文件无法捕获这部分内容。

解决方案

使用subprocess模块替换os.system,捕获命令的输出流,再通过Python的print方法输出(此时会经过Logger的拦截逻辑),同时完善Logger的flush方法避免输出缓冲。

修改后的teststout.py代码

import os
import sys
import subprocess

class Logger(object):
    def __init__(self):
        self.terminal = sys.stdout
        self.log = open("odareplayout.log", "a")

    def write(self, message):
        self.terminal.write(message)
        self.log.write(message)

    def flush(self):
        # 同时刷新终端和日志文件的缓冲区,确保输出实时写入
        self.terminal.flush()
        self.log.flush()

sys.stdout = Logger()

def main():
    print('Hello World')
    cmd = 'ansible-playbook test3.yaml'
    # 用subprocess捕获命令输出,实时处理
    process = subprocess.Popen(
        cmd,
        shell=True,
        stdout=subprocess.PIPE,
        stderr=subprocess.STDOUT,  # 将stderr合并到stdout一起处理
        text=True  # 以文本模式读取输出,避免字节流处理
    )
    # 循环读取输出的每一行,直到进程结束
    for line in iter(process.stdout.readline, ''):
        print(line, end='')  # end=''避免重复换行,因为命令输出本身带换行符
    # 等待进程执行完成,获取返回码
    process.wait()

if __name__ == '__main__':
    main()

代码说明

  • subprocess.Popen:创建子进程执行命令,通过stdout=subprocess.PIPE捕获输出流,stderr=subprocess.STDOUT将错误输出合并到标准输出,方便统一处理。
  • iter(process.stdout.readline, ''):循环读取输出的每一行,实现实时输出,避免等待命令执行完才一次性输出。
  • print(line, end=''):输出读取到的内容,此时会触发Logger的write方法,同时写入终端和日志文件。
  • 完善的flush方法:确保输出内容实时刷新到终端和日志文件,不会因为缓冲区导致内容延迟写入。

执行修改后的代码,odareplayout.log会同时记录Hello World和ansible-playbook的所有输出内容。

内容的提问来源于stack exchange,提问作者Akash-BLR

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 08:53:18