kqueue 追踪文件变化 - 处理前一个事件时丢失事件的可能性?

3 投票
1 回答
567 浏览
提问于 2025-04-17 18:16

我在做什么

我正在实现一个基于python和kqueue(FreeBSD)的解决方案,用来监控一个特定的日志文件。当这个日志文件被写入时,kqueue会触发一个事件,然后我的python脚本中的另一个函数会处理这个变化。

我为什么要这样做

最终,我是想把最新的日志文件条目发送到其他地方,作为一个简单粗暴的记账系统的一部分。

我觉得我需要知道什么

1) 由于日志文件可能会经历高流量的情况,我想知道在把最新的条目传递给日志文件时,是否会“错过”新进来的条目?因为kqueue是一个“队列”,我以为不会,但历史告诉我,我通常会因为这样的假设而感到尴尬。

2) kqueue是否保证每个事件都会触发,还是可能会有多个事件被漏掉?我想象的情况是,日志文件几乎同时产生两个独立的条目。

任何智慧或建议都很受欢迎。

1 个回答

4

你的怀疑是对的。:-)

在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”。你可以监视这个目录和文件,检查新文件的创建,以捕捉这种情况。

撰写回答