将后台进程的输出记录到文件中

问题描述 投票:1回答:1

我有耗时的SNMP Walk任务来执行,我正在使用Popen命令将其作为后台进程运行。如何在日志文件中捕获此后台任务的输出。在下面的代码中,我试图在ip_list中的每个IP上执行snampwalk,并将所有结果记录到abc.txt。但是,我看到生成的文件abc.txt为空。

下面是我的示例代码-

import subprocess
import sys

f = open('abc.txt', 'a+')

ip_list = ["192.163.1.104", "192.163.1.103", "192.163.1.101"]

for ip in ip_list:
    cmd = "snmpwalk.exe -t 1 -v2c -c public "
    cmd = cmd + ip
    print(cmd)
    p = subprocess.Popen(cmd, shell=True, stdout=f)
    p.wait()
f.close()

print("File output - " + open('abc.txt', 'r').read())

命令的示例输出对于每个IP可以是这样的-

sysDescr.0 = STRING: Software: Whistler Version 5.1 Service Pack 2 (Build 2600)
sysObjectID.0 = OID: win32
sysUpTimeInstance = Timeticks: (15535) 0:02:35.35
sysContact.0 = STRING: unknown
sysName.0 = STRING: UDLDEV
sysLocation.0 = STRING: unknown
sysServices.0 = INTEGER: 72
sysORID.4 = OID: snmpMPDCompliance 

我已经尝试过Popen。但是,如果这是耗时的后台进程,则不会将输出记录到文件中。但是,当我尝试运行ls / dir之类的后台进程时,它可以工作。任何帮助表示赞赏。

python linux subprocess stdout popen
1个回答
0
投票

这里的主要问题是我对Popen的功能及其工作原理的期望。p.wait()在此将等待过程完成,然后再继续,这就是为什么ls例如有效,但耗时的任务无效的原因。在调用p.stdout.flush()之前,没有任何东西会自动刷新输出。

您的设置方式更适合用于:

  1. 执行命令
  2. 等待退出
  3. 捕获输出
  4. 然后使用它。对于您的用例,最好使用替代库

使用stdout=subprocess.PIPE并自己进行捕获。这将意味着:
import subprocess
import sys

ip_list = ["192.163.1.104", "192.163.1.103", "192.163.1.101"]
with open('abc.txt', 'a+') as output:
    for ip in ip_list:
        print(cmd := f"snmpwalk.exe -t 1 -v2c -c public {ip}")
        process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE) # Be wary of shell=True
        while process.poll() is None:
            for c in iter(lambda: process.stdout.read(1), ''):
                if c != '':
                    output.write(c)

with open('abc.txt', 'r') as log:
    print("File output: " + log.read())

这里要删除的关键是process.poll(),它检查进程是否已完成,如果没有完成,我们将尝试使用process.stdout.read(1)捕获输出以一次读取一个字节。如果您知道有新行要来,则可以将这三行切换为output.write(process.stdout.readline()),一切都准备就绪。

© www.soinside.com 2019 - 2024. All rights reserved.