如何在Python中生成另一个进程并捕获输出?

3

我正在学习Python,但在PERL和PHP方面有大约16年的经验。

我正在尝试使用Python获取ngrep的输出并将其写入日志文件,同时也要跟踪日志文件。我在网上看到了一些示例,但有些已经过时,而其他一些则使用不被鼓励的shell=True。

在Perl中,我只需使用类似以下内容的命令

#!/usr/bin/perl
open(NGFH,"ngrep -iW byline $filter");
while ($line = <NGFH>) {
    open(LOG,">> /path/to/file.log")
    // highlighting, filtering, other sub routine calls
    print LOG $line
}

我已经让tail工作了,但ngrep没有。我希望能够无限运行并将ngrep的流过滤后输出到日志文件中。我无法让ngrep的输出显示在stdout中,所以这就是我的极限了。我原本期望能够在更新日志文件时看到数据文件tail和ngrep的输出。目前我只是使用bash来运行以下命令。

echo "." >> /path/to/ngrep.log

谢谢!

这是我目前的翻译...

更新 现在似乎可以正常工作了。不过我不知道如何改进它。

import subprocess
import select
import re

log = open('/path/to/ngrep.log','a+',0)
print log.name

n = subprocess.Popen(['ngrep', '-iW', 'byline'],\
    stdout=subprocess.PIPE,stderr=subprocess.STDOUT)
p = select.poll()
p.register(n.stdout)

f = subprocess.Popen(['tail','-F','-n','0','/path/to/tailme.log'],\
    stdout=subprocess.PIPE,stderr=subprocess.PIPE)
p2 = select.poll()
p2.register(f.stdout)

def srtrepl(match):
    if match.group(0) == 'x.x.x.x':
        # do something
    if match.group(0) == 'x.x.y.y':
        # do something else

    return '\033[92m'+ match.group(0) + '\033[0m'

while True:
    if p.poll(1):
        line = n.stdout.readline()
        s = re.compile(r'(8.8.(4.4|8.8)|192.168.[0-9]{1,3}.[0-9]{1,3})' )
        print s.sub( srtrepl, line )
        log.write(n.stdout.readline())

    if p2.poll(1):
        print f.stdout.readline().rstrip('\n')

为什么需要tail和ngrep?你可以在这里使用“纯”Python代码。 - Kijewski
@tdelaney 我想要交错记录。 - Steve Hernandez
1
@Kay 但是 ngrep 是一个不同的工具 - _"ngrep 是一个 pcap 感知工具,它允许您指定扩展正则表达式来匹配数据包的数据负载"_。 - tdelaney
@Kay 我正在学习Python,但想看看是否可以将我现有的PERL脚本转换为Python并提高性能,并在未来的项目中使用Python。我目前编写了一些用于防火墙更新、允许动态主机通过防火墙、IRC以及其他一些功能的PERL脚本,例如查找过时的WordPress和Joomla安装程序以及PHP文件指纹识别。 - Steve Hernandez
你只想让输出到达标准输出吗?如果是这样,在调用时跳过stdout=subprocess.PIPE,等待ngrep完成后再杀死tail - tdelaney
显示剩余6条评论
1个回答

1

将您的Perl代码在Python中模拟:

#!/usr/bin/env python3
from subprocess import Popen, PIPE

with Popen("ngrep -iW byline".split() + [filter_], stdout=PIPE) as process, \
     open('/path/to/file.log', 'ab') as log_file:
    for line in process.stdout: # read b'\n'-separated lines
        # highlighting, filtering, other function calls
        log_file.write(line)

它启动ngrep进程,传递filter_变量,并将输出追加到日志文件中,同时允许您在Python中进行修改。请参见Python:从subprocess.communicate()读取流输入(可能会出现缓冲问题:检查ngrep是否支持--line-buffered选项,就像grep一样,如果要跟踪file.log,则buffering = 1 传递给open(),以启用行缓冲(仅在文本模式中可用)或在log_file.write(line)之后调用log_file.flush())。

您也可以在纯Python中模拟ngrep


如果您想同时读取多个进程的输出(例如您的情况中的ngreptail),那么您需要能够无阻塞地读取管道,例如使用线程、async.io

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接