Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 将后台进程的输出记录到文件中_Python_Linux_Subprocess_Stdout_Popen - Fatal编程技术网

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

Python 将后台进程的输出记录到文件中,python,linux,subprocess,stdout,popen,Python,Linux,Subprocess,Stdout,Popen,我有一个耗时的SNMP walk任务要执行,我正在使用Popen命令作为后台进程运行该任务。如何在日志文件中捕获此后台任务的输出。在下面的代码中,我尝试在IP_列表中的每个IP上进行SNAMPWARK,并将所有结果记录到abc.txt。但是,我看到生成的文件abc.txt是空的 下面是我的示例代码- import subprocess import sys f = open('abc.txt', 'a+') ip_list = ["192.163.1.104", "192.163.1.103

我有一个耗时的SNMP walk任务要执行,我正在使用Popen命令作为后台进程运行该任务。如何在日志文件中捕获此后台任务的输出。在下面的代码中,我尝试在IP_列表中的每个IP上进行SNAMPWARK,并将所有结果记录到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 

我已经试过波本了。但如果是一个耗时的后台进程,它不会将输出记录到文件中。然而,当我尝试运行像ls/dir这样的后台进程时,它会工作。非常感谢您的帮助。

这里的主要问题是对
Popen
的预期以及我假设它是如何工作的。
p.wait()。在调用
p.stdout.flush()
之前,不会自动刷新输出

您的设置方式更适合于:

  • 执行命令
  • 等待出口
  • 渔获量
  • 然后用它工作。对于您的用例,您最好使用另一个库使用
    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())
    ,然后您就都准备好了。

    这里的主要问题是对
    Popen
    的预期以及它的工作方式。
    p.wait()。在调用
    p.stdout.flush()
    之前,不会自动刷新输出

    您的设置方式更适合于:

  • 执行命令
  • 等待出口
  • 渔获量
  • 然后用它工作。对于您的用例,您最好使用另一个库使用
    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())
    ,然后您就都设置好了。

    如果您愿意,您可以将
    Popen
    输出重定向到一个文件,
    Popen(…,stdout=…)
    。导入子流程import sys f=open('abc.txt',w')cmd“snmpwalk.exe-t1-v2c-c public 192.168.34.3”p=subprocess.Popen(cmd,shell=True,stdout=f)sys.stdout.flush()f.close()@Torxed,我已经尝试过将文件对象传递给stdout。但是它不会将数据写入文件,您也可以读取
    handle.stdout.read()
    时不时?:)@Torxed我也试过了,但是stout.read不会在长时间的后台进程中打印任何内容。因此,这并不能解决问题。如果您愿意,您可以将
    Popen
    输出重定向到一个文件,
    Popen(…,stdout=…)
    。导入子进程导入sys f=open('abc.txt','w')cmdsnmpwalk.exe-t1-v2c-c public 192.168.34.3“p=subprocess.Popen(cmd,shell=True,stdout=f)sys.stdout.flush()f.close()@Torxed,我尝试过将文件对象传递给stdout。但它不会将数据写入文件,您也可以读取
    handle.stdout.read()
    时不时?:)@Torxed我也尝试过,但是stout.read在很长的后台进程中不会打印任何内容。因此,这并不能解决问题。谢谢您的解释。但是,这并不能解决问题。文件中没有捕获任何内容。如果是空的,则该命令确实没有输出。是否可以erhaps编辑您的问题,为我们提供命令的示例输出?我在问题中添加了示例输出,供您参考。此外,当我在cmd中手动尝试命令时,它工作正常,我在console@shivamgupta我很难理解什么对你不起作用。下面是一个SNMP的详细视频服务器侦听(底部),当我运行上面的代码(中间窗口)和这个答案中的代码(顶部窗口)时,
    abc.txt
    文件的尾部:-如您所见,
    abc.txt
    的输出几乎是瞬时的,我不太确定“文件中没有捕获任何内容”是什么意思“显然是这样。我在Linux机器上运行了这个,因为我找不到NetSNMP的windows二进制文件。也许你编译得很奇怪?输出到
    stderr
    ?我正在跟踪您。但是没有任何内容被打印到日志文件中。这可能是windows的问题,因为我使用windows machinethanks供您解释。但是,这并不能解决问题。文件中未捕获任何内容。如果是空的话,那么命令就没有输出了。您是否可以编辑您的问题,为我们提供命令的示例输出?我在问题中添加了示例输出,供您参考。另外,当我在cmd中手动尝试该命令时,它工作正常,并且在console@shivamgupta我很难明白什么对你不起作用。下面是一个SNMP服务器监听的详细视频(底部),当我运行上面的代码(中间窗口)和这个答案中的代码(顶部窗口)时,
    abc.txt
    文件的尾部:-如您所见,
    abc.txt
    的输出接近