python sys.stdin.read() 来自 tail -f

python sys.stdin.read() from tail -f

为什么 sys.stdin.read() 不从 tail -f 读取管道输入?

#!/usr/bin/env python
import sys
from geoip import geolite2
def iplookup(srcip):
        for ip in srcip.split("\n"):
                try:
                        print(geolite2.lookup(ip))
                except:
                        pass
source = sys.stdin.read()
iplookup(source)

tail -f /var/log/bleh.log | grep -oE '((1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])' | python mygeoip.py

您可以将 sys.stdin 用作迭代器,而不是先尝试从中读取。

def iplookup(srcip):
    for ip in srcip:
        ip = ip.strip()
        try:
            print(geolite2.lookup(ip))
        except:
            pass

iplookup(sys.stdin)

read() 读取直到到达 EOF。 EOF 字符在执行 close() 时添加,或者您可以显式添加它。

您的文件没有任何 EOF。修改您的程序以读取固定大小的块或迭代 leadline()。

您可以使用 fileinput :

import sys
from geoip import geolite2
import fileinput

def iplookup(srcip):
        for ip in srcip.split("\n"):
                try:
                        print(geolite2.lookup(ip))
                except:
                        pass

for line in fileinput.input():
    iplookup(line)

从好的方面来说,您的脚本也会自动接受文件名作为参数。

None 的其他答案(甚至 fileinput)完全解决了缓冲问题,因此不适用于 tail -f 的小输出。

来自the python man page

Note that there is internal buffering in xreadlines(), readlines() and file-object iterators ("for line in sys.stdin") which is not influenced by this option. To work around this, you will want to use "sys.stdin.readline()" inside a "while 1:" loop.

换句话说你想要的是:

while True:
    line = sys.stdin.readline()
    iplookup(line)