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



我有耗时的SNMP步行任务来执行,我正在使用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 等后台进程时,它可以工作。任何帮助,不胜感激。

这里的主要问题是我对Popen做什么以及我假设它如何工作的期望。p.wait()这里将等待该过程完成,然后再继续,这就是为什么例如ls有效但更耗时的任务不起作用的原因。在您调用p.stdout.flush()之前,不会自动刷新输出。

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

  1. 执行命令
  2. 等待退出
  3. 捕获输出

然后使用它。对于您的用例,您最好使用替代库或使用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()),一切就绪。

最新更新