python:连续读取文件,即使在logrotate之后也是如此

时间:2014-08-27 21:28:38

标签: python file

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

while True:
    line = f.readline()
    if line:
        print line,
    else:
        time.sleep(0.1)

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

即。我需要做tail -F会做的事情。

我正在使用python 2.7

3 个答案:

答案 0 :(得分:12)

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

看起来像这样:

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)

我怀疑这可以在Windows上运行,但是由于您在tail方面发言,我猜这不是问题。 :)

答案 1 :(得分:4)

您可以通过跟踪文件中的位置并在想要阅读时重新打开来实现。当日志文件旋转时,您会注意到该文件较小,并且自重新打开后,您也可以处理任何取消链接。

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)

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

答案 2 :(得分:1)

感谢@tdelaney和@ Dolda2000的答案,我最终得到了以下内容。它应该适用于Linux和Windows,并且还可以处理logrotate的copytruncatecreate选项(分别复制然后将大小截断为0并移动然后重新创建文件)。

file_name = 'my_log_file'
seek_end = True
while True:  # handle moved/truncated files by allowing to reopen
    with open(file_name) as f:
        if seek_end:  # reopened files must not seek end
            f.seek(0, 2)
        while True:  # line reading loop
            line = f.readline()
            if not line:
                try:
                    if f.tell() > os.path.getsize(file_name):
                        # rotation occurred (copytruncate/create)
                        f.close()
                        seek_end = False
                        break
                except FileNotFoundError:
                    # rotation occurred but new file still not created
                    pass  # wait 1 second and retry
                time.sleep(1)
            do_stuff_with(line)

使用copytruncate选项时的限制是,如果在时间休眠时将行附加到文件,并且在唤醒之前发生旋转,则最后一行将是&#34 ;丢失&#34; (他们仍然会在现在的#34;旧的#34;日志文件中,但我看不到一个体面的方式来跟随&#34;该文件完成阅读它。此限制与&#34;移动和创建&#34;无关。 create选项因为f描述符仍将指向重命名的文件,因此在描述符关闭并再次打开之前将读取最后一行。