我正在写一个Python脚本,它需要tail -f一个日志文件。
操作系统为RHEL,运行Linux 2.6.18。
我认为正常的方法是使用带睡眠的无限循环,不断地轮询文件。
但是,既然我们使用的是Linux,我想我也可以使用pyinotify (https://github.com/seb-m/pyinotify)或Watchdog (https://github.com/gorakhargosh/watchdog)之类的东西来代替。
这有什么好处/坏处?
我听说使用sleep(),如果文件增长很快,你可能会错过事件--这可能吗?我还以为GNU tail也使用睡眠呢?
干杯,维克多
发布于 2013-04-03 05:45:01
最干净的解决方案在很多方面都是inotify -毕竟,这或多或少就是它的初衷。如果日志文件变化非常快,那么您可能会面临几乎经常被唤醒的风险,这不一定是特别有效的-但是,您总是可以通过在inotify文件句柄返回事件后添加自己的短暂延迟来缓解这种情况。在实践中,我怀疑这在大多数系统上都是一个问题,但我认为在您的系统CPU资源非常紧张的情况下,这一点值得一提。
我不明白sleep()方法怎么会错过文件更新,除非文件被截断或旋转(即重命名并创建另一个同名的文件)。这些都是棘手的情况,无论您如何处理,您都可以使用一些技巧,比如定期按名称重新打开文件来检查轮换。请阅读tail手册页,因为它可以处理许多这样的情况,特别是对于日志文件来说,这种情况非常常见(日志轮换被广泛认为是一种良好的做法)。
当然,sleep()的缺点是,您最终会在两者之间延迟批量读取,而且即使文件没有变化,您也会有不断唤醒和轮询文件的开销。但是,如果您这样做,比方说每秒一次,那么在大多数系统上开销可能是不可察觉的。
我会说inotify是最好的选择,除非你想保持兼容性,在这种情况下,使用sleep()的简单回退仍然是相当合理的。
编辑:
我刚刚意识到我忘了提--检查文件被重命名的一个简单方法是在打开的文件句柄上执行os.fstat(fd.fileno()),在打开的文件名上执行os.stat(),然后比较结果。如果os.stat()失败,则该错误将告诉您该文件是否已被删除,如果没有,则比较st_ino ( inode number)字段将告诉您该文件是否已被删除,然后替换为同名的新文件。
检测截断比较困难-有效地说,您的读取指针保持在文件中的相同偏移量,读取将不会返回任何内容,直到文件内容大小恢复到您所在的位置-然后文件将正常从该位置读取。如果您经常调用os.stat(),您可以检查文件大小是否向后移动-或者,您可以使用fd.tell()记录您在文件中的当前位置,然后对文件末尾执行显式查找,然后再次调用fd.tell()。如果该值较低,则文件在您的控制下已被截断。这是一个安全的操作,只要你保持原始文件的位置,因为你总是可以在检查后找回它。
或者,如果你正在使用inotify,你可以只观察父目录的变化。
请注意,文件可以被截断为非零大小,但我怀疑这种情况是否可能发生在日志文件上--常见的情况是被删除并替换,或者被截断为零。此外,我不知道您如何检测到文件被截断,然后立即填充到您当前位置之外的情况,除非通过记住最近的N个字符并比较它们,但这是一件非常糟糕的事情。我想inotify在这种情况下会告诉你文件已经被修改了。
https://stackoverflow.com/questions/15699566
复制相似问题