kqueue 追踪文件变化 - 处理前一个事件时丢失事件的可能性?
我在做什么
我正在实现一个基于python和kqueue(FreeBSD)的解决方案,用来监控一个特定的日志文件。当这个日志文件被写入时,kqueue会触发一个事件,然后我的python脚本中的另一个函数会处理这个变化。
我为什么要这样做
最终,我是想把最新的日志文件条目发送到其他地方,作为一个简单粗暴的记账系统的一部分。
我觉得我需要知道什么
1) 由于日志文件可能会经历高流量的情况,我想知道在把最新的条目传递给日志文件时,是否会“错过”新进来的条目?因为kqueue是一个“队列”,我以为不会,但历史告诉我,我通常会因为这样的假设而感到尴尬。
2) kqueue是否保证每个事件都会触发,还是可能会有多个事件被漏掉?我想象的情况是,日志文件几乎同时产生两个独立的条目。
任何智慧或建议都很受欢迎。
1 个回答
你的怀疑是对的。:-)
在kqueue中,一个“事件”会被“扩展”,如果在处理一个相同的事件时,第二个相同的事件又发生了。也就是说,假设在底层事件的顺序是这样的:
1: you start monitoring the log file for writes
2: something writes to the log file (this adds a "write" notice to the kqueue)
3: your process is notified, but does not have a chance to go look yet
4: something (same something as step 2, or different, does not matter)
writes more to the log file (this merely "expands" the existing notice,
with no effect in this case)
5: your process finally gets a chance to read the "file was written" notice
from the kqueue
当第5步发生时,“文件被写入”的通知只会有一个。接下来就得靠你的代码来判断到底写入了多少内容。例如,你可以在第1步使用fstat()
来检查文件的长度,然后在第5步后再用一次fstat()
。如果文件只是不断地添加内容,那么这两个时刻的大小差就是你关心的“新数据”。
注意,如果你在第1步看到的是100字节,而在第5步后看到的是500字节——比如在第7步:
7: you fstat the file
然后又收到了另一个“文件被写入”的通知,这可能意味着实际上在第6步时文件又被写入了一次。所以你应该做好准备,可能在更晚的步骤中发现没有增加任何字节,尽管你收到了字节被添加的通知,因为你可能已经在通知被添加到kqueue后就读取了这些字节。
如果你在监视syslog
类型的日志,要注意这些日志会被“翻转”,也就是文件会被重命名(然后有时会被压缩等),接着创建一个新文件,比如“messages”变成“messages.0.bz2”,然后再创建一个新的“messages”。你可以监视这个目录和文件,检查新文件的创建,以捕捉这种情况。