python:连续读取文件,即使它已经被logrotated

Mar*_*ter 6 python file

我有一个简单的python脚本,我连续读取logfile(相同tail -f)

while True:
    line = f.readline()
    if line:
        print line,
    else:
        time.sleep(0.1)
Run Code Online (Sandbox Code Playgroud)

在通过logrotate旋转后,如何确保仍然可以读取日志文件?

即我需要做同样的tail -F事情.

我在用 python 2.7

Dol*_*000 13

只要您计划在Unix上执行此操作,最可靠的方法是检查以便打开的文件仍然引用与名称相同的i-node,并在不再是这种情况时重新打开它.您可以在字段中从os.stat和获取文件的i编号.os.fstatst_ino

它可能看起来像这样:

import os, sys, time

name = "logfile"
current = open(name, "r")
curino = os.fstat(current.fileno()).st_ino
while True:
    while True:
        buf = current.read(1024)
        if buf == "":
            break
        sys.stdout.write(buf)
    try:
        if os.stat(name).st_ino != curino:
            new = open(name, "r")
            current.close()
            current = new
            curino = os.fstat(current.fileno()).st_ino
            continue
    except IOError:
        pass
    time.sleep(1)
Run Code Online (Sandbox Code Playgroud)

我怀疑这适用于Windows,但是因为你说的是tail,我猜这不是问题.:)


tde*_*ney 5

您可以通过跟踪文件中的位置并在需要阅读时重新打开它来完成此操作。当日志文件轮换时,您会注意到文件变小,并且由于您重新打开,您也可以处理任何取消链接。

import time

cur = 0
while True:
    try:
        with open('myfile') as f:
            f.seek(0,2)
            if f.tell() < cur:
                f.seek(0,0)
            else:
                f.seek(cur,0)
            for line in f:
                print line.strip()
            cur = f.tell()
    except IOError, e:
        pass
    time.sleep(1)
Run Code Online (Sandbox Code Playgroud)

此示例隐藏了诸如找不到文件之类的错误,因为我不确定 logrotate 详细信息,例如文件不可用的一小段时间。

注意:在 python 3 中,情况有所不同。常规open转换bytesstr和 用于该转换的临时缓冲区意味着seektell无法正常运行(除非寻找 0 或文件末尾)。相反,以二进制模式(“rb”)打开并逐行手动进行解码。您必须知道文件编码以及该编码的换行符是什么样的。对于 utf-8 来说,它b"\n"(utf-8 优于 utf-16 的原因之一,顺便说一句)。