【问题标题】:Is it possible for `tail` to emit incomplete lines?`tail` 是否有可能发出不完整的行?
【发布时间】:2023-03-24 17:52:02
【问题描述】:

我正在使用tail -F log | python parse.py 来监控和解析不断增长的日志文件,但出现了一些解析错误,这可能是由于从日志文件中读取不完整的行所致。

tail 是否有可能发出不完整的行?

在解析器中,我正在使用如下代码读取行:

import csv
import sys

reader = csv.reader(sys.stdin)
for row in reader
    # process

【问题讨论】:

    标签: python bash parsing logging tail


    【解决方案1】:

    tail 可能会发出“无法解析的行”——但前提是将无效行写入文件。有点循环论证,但这里有一个例子说明它是如何发生的:

    • 你在 /var/log/syslog 上尾随 -f

    • syslog-ng 在跨块写入过程中死机(扇区为 512 字节,您的文件系统块大小很可能更大,虽然可能不会比 4096 大多少.. 所以,syslog 有 9k 的数据缓冲写出,它通过 4k 字节页面,在它可以写入下一个 4k + 1k 系统日志之前死掉。至少在 ext2 上,即使在 fsck 之后,它也会最终成为部分写入。ext3?..呵呵。我一直在做嵌入式,我不记得了......但是,我希望不会......但谁说你写的数据总是正确的?你可能会得到一个非致命的不包含您期望的换行符的字符串格式错误。

    • 然后,您将有一个不以换行符(甚至是 \0)终止的部分行,并且下次系统日志启动并开始附加时,它只会附加到末尾没有“有效”记录概念的文件。所以第一个新记录会是垃圾,但下一个就可以了。

    这很容易锻炼..

    在一个窗口中

    tail -f SOMEFILE

    在另一个窗口中

    echo FOO >>SOMEFILE
    echo BAR >>SOMEFILE
    printf NO_NEWLINE >>SOMEFILE
    echo I_WILL_HAVE_THE_LAST_LINE_PREFIXED_TO_ME_CAUSING_NERD_RAGE >>SOMEFILE
    

    由于 Linux 的尾部默认使用 inotify,因此无论读取什么都将获取没有换行符的最后一行,并等待下一个换行符出现,将 NO_NEWLINE 附加到它认为是“最新行”的开头。

    如果您想以“pythonic”的方式执行此操作,如果您使用的是 Linux - 使用 inotify,如果您使用的是 OSX 或 BSD,请使用“knotty”并否定使用“tail”作为输入管道和自己看文件。

    如果您也使用“截断时重新同步”,Tail 可能会做一些奇怪的事情 - 即,如果文件在读取过程中归零并重新启动,您可能会在读取时获得一些奇怪的数据量,因为“tail”会关闭之前打开的文件句柄以换取新的文件句柄。

    【讨论】:

    • 虽然有可能,但非常罕见。我猜提问者的 python 脚本出错的可能性要高得多。
    • @Perry,我已经更新了问题并添加了我用来阅读日志的代码。
    • 您确定日志中的行是逗号分隔值吗?
    【解决方案2】:

    既然你改变了我的问题.. 新的答案! :p

    reader = csv.reader(sys.stdin)
    for row in reader: 
        try:
            validate_row_data_somehow(row)
            do_things_with_valid_row(row)
        except:
            print "failed to process row", `row`
    

    【讨论】:

    • 更改问题需要不同的答案通常会导致我对该问题投反对票。
    • 我今天感觉很慷慨。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-10-23
    • 1970-01-01
    • 2011-10-01
    • 2023-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多