为啥inotify会丢失事件?
Posted
技术标签:
【中文标题】为啥inotify会丢失事件?【英文标题】:Why is inotify losing events?为什么inotify会丢失事件? 【发布时间】:2011-12-10 06:15:39 【问题描述】:我需要使用 Perl 和 Linux::Inotify2 处理大量(约 100 秒)系统日志消息。
我编写了一个连续生成日志消息的测试脚本。为了处理事件,我的 Perl 脚本如下所示-
#!/usr/bin/perl
use Linux::Inotify2 ;
use Time::HiRes qw(usleep nanosleep);
# create a new object
my $inotify = new Linux::Inotify2
or die "Unable to create new inotify object: $!" ;
# create watch
$inotify->watch ("/var/log/messages", IN_ACCESS|IN_OPEN|IN_CLOSE|IN_MODIFY|IN_Q_OVERFLOW)
or die "watch creation failed" ;
my $count=0;
while ()
my @events = $inotify->read;
unless (@events > 0)
print "read error: $!";
last ;
#printf "mask\t%d\n", $_->mask foreach @events ;
$count++;
print $count."\n";
usleep(100000);
如果我取消注释 usleep 函数以模拟处理,我注意到当我停止日志生成器脚本时,inotify 脚本没有赶上它。换句话说, inotify Perl 脚本正在丢失事件。
我也没有看到任何溢出消息。
我如何确保即使我的处理速度很慢,我也不会丢失消息。换句话说,我如何定义一个可以临时存储消息的“缓冲区”?
【问题讨论】:
您使用的是哪个模块?有不止一个 Perl 接口可以进行 inotify。 另外,您似乎缺少一些代码。例如,你永远不会用任何东西填充@events
。你的usleep
电话不在任何循环中。
您如何确定缺少事件?要计算您可以尝试的事件数量:$count += @events
.
我没有看到任何检查队列是否溢出的尝试。另外,/proc/sys/fs/inotify/max_queued_events
设置为什么?
您可以考虑配置 rsyslog 以将 syslog 消息发送到您的 perl 进程,而不是使用文件系统 / inotify 作为中介。
【参考方案1】:
我将尝试解决您的根本问题,即使它不能完全回答您的问题。
我认为使用 inotify 解决这个问题的方法太低级了。如果我是你,我会寻找一个更高级别的解决方案,让你从寻找新事件的细节中解放出来,让你专注于处理日志事件。当已经有很多好的***可用时,无需重新发明***。
我的第一选择是使用现代的 syslog 守护程序(我个人更喜欢 Syslog-NG,但 rsyslog 也可以很好地工作),并将其直接绑定到您的脚本。当新事件出现时,您的脚本无需执行所有跟踪工作,您的脚本只处理stdin
,并且系统日志守护程序会在新日志进入时自动将新日志发送到您的脚本。我已经在无数次成功地使用了这种方法场合。
我的第二个选择是让更高级别的 Perl 模块尽可能多地完成繁重的工作。我要寻找的第一个地方是File::Tail
。和以前一样,这让您摆脱了查看文件本身的问题,让您专注于处理。
【讨论】:
【参考方案2】:查看Inotify on CPAN 并尝试使用回调检查所有错误:
$inotify->watch ("/etc/passwd", IN_ACCESS | IN_MODIFY, sub
my $e = shift;
print "$e->wname was accessed\n" if $e->IN_ACCESS;
print "$e->wname was modified\n" if $e->IN_MODIFY;
print "$e->wname is no longer mounted\n" if $e->IN_UNMOUNT;
print "events for $e->wname have been lost\n" if $e->IN_Q_OVERFLOW;
);
此外,您正在关注文件中的几乎所有事件。我只关注修改事件或一小部分事件,看看问题是否仍然存在。
【讨论】:
以上是关于为啥inotify会丢失事件?的主要内容,如果未能解决你的问题,请参考以下文章