1

我正在编写一个需要tail -f日志文件的 Python 脚本。

操作系统是 RHEL,运行 Linux 2.6.18。

我认为正常的方法是使用无限循环和睡眠,不断轮询文件。

但是,由于我们在 Linux 上,我想我也可以使用诸如 pinotify ( https://github.com/seb-m/pyinotify ) 或 Watchdog ( https://github.com/gorakhargosh/watchdog )之类的东西反而?

这有什么优点/缺点?

我听说使用sleep(), 如果文件快速增长,您可能会错过事件 - 这可能吗?我认为 GNU tail 无论如何也使用睡眠?

干杯,维克多

4

1 回答 1

6

最干净的解决方案将是 inotify 在许多方面 - 毕竟这或多或少正是它的目的。如果日志文件的变化非常迅速,那么您可能会面临几乎不断被唤醒的风险,这不一定特别有效 - 但是,您始终可以通过在 inotify 文件句柄返回事件后添加自己的短暂延迟来缓解这种情况. 在实践中,我怀疑这在大多数系统上会是一个问题,但我认为值得一提,以防您的系统在 CPU 资源上非常紧张。

我看不出这种sleep()方法会如何错过文件更新,除非文件被截断或旋转(即重命名并创建另一个同名文件)。无论您做什么,这些都是棘手的情况,您可以使用诸如定期按名称重新打开文件以检查旋转的技巧。阅读tail手册页,因为它处理了许多此类情况,特别是日志文件将非常普遍(日志轮换被广泛认为是一种很好的做法)。

当然,缺点sleep()是您最终会批量读取并在两者之间产生延迟,而且即使文件没有更改,您也会有不断唤醒和轮询文件的开销。但是,如果您这样做,例如每秒一次,那么开销在大多数系统上可能并不明显。

我会说 inotify 是最好的选择,除非你想保持兼容,在这种情况下,简单的后备使用sleep()仍然是相当合理的。

编辑:

我刚刚意识到我忘了提及 - 检查文件是否被重命名的一种简单方法是os.fstat(fd.fileno())对打开的文件句柄和打开os.stat()的文件名执行 a 并比较结果。如果os.stat()失败,则错误将告诉您文件是否已被删除,如果没有,则比较st_ino(inode 编号)字段将告诉您文件是否已被删除,然后替换为同名的新文件。

检测截断更难 - 实际上,您的读取指针在文件中保持相同的偏移量,并且在文件内容大小恢复到原来的位置之前,读取将不会返回任何内容 - 然后文件将从该点正常读取。如果您os.stat()经常调用,您可以向后检查文件大小 - 或者您可以使用fd.tell()记录您在文件中的当前位置,然后显式查找文件末尾并fd.tell()再次调用。如果该值较低,则该文件已被您截断。只要您保留原始文件位置,这是一个安全的操作,因为您始终可以在检查后返回它。

或者,如果您仍然使用 inotify,则可以只观察父目录的更改。

请注意,文件可以被截断为非零大小,但我怀疑日志文件可能会发生这种情况 - 常见情况将被删除和替换,或者被截断为零。另外,我不知道您如何检测文件被截断然后立即填充到您当前位置之外的情况,除非记住最近的 N 个字符并比较它们,但这是一件非常糟糕的事情做。我认为 inotify 只会告诉您在这种情况下文件已被修改。

于 2013-04-02T21:45:00.630 回答