3

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

我正在尝试获取 ngrep 的输出并使用 Python 将其写入日志文件,同时还跟踪日志文件。我在网上看到了一些示例,但有些示例似乎过时且过时,而其他示例则不鼓励使用 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
}

我已经开始工作了,但 ngrep 没有。我希望能够无限地运行它并在过滤后将流从ngrep输出到日志文件。我无法让 ngrep 的输出显示在标准输出中,所以这就是我所得到的。我希望能够在更新日志文件时看到数据文件尾部,并看到来自 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')
4

1 回答 1

1

要在 Python 中模拟您的 perl 代码:

#!/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=1open(), 以启用行缓冲(仅在文本模式下可用)或调用log_file.flush()之后log_file.write(line))。

ngrep您也可以在纯 Python 中进行模拟。


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

于 2016-01-03T01:36:34.013 回答