为什么 inotify 会丢失事件?
我需要使用 Perl 和 Linux::Inotify2。
我编写了一个连续生成日志消息的测试脚本。为了处理事件,我的 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 脚本正在丢失事件。
我也没有看到任何溢出消息。
我如何确保即使我的处理速度很慢,我也不会丢失消息。换句话说,如何定义一个可以临时存储消息的“缓冲区”?
I need to process large (~100s) of syslog messages using Perl and Linux::Inotify2.
I wrote a test script which generates log messages continuously. To process events, my Perl script looks like this-
#!/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);
}
If I un-comment usleep function to simulate processing, I notice that when I stop the log generator script, the inotify script doesn't catch up with it. In other words, the inotify Perl script is losing events.
Neither do I see any Overflow message.
How do I make sure that even if my processing is slow, I don't lose messages. In other words, how do I define a "buffer" where messages can be stored temporarily?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我将尝试解决您的根本问题,即使它不能完全回答您的问题。
我认为使用 inotify 来解决这个问题的方法太低级了。如果我是您,我会寻找一种更高级别的解决方案,使您从查找新事件的细节中解放出来,并让您专注于处理日志事件。当已经有很多好的可用工具时,无需重新发明轮子。
我的第一个选择是使用现代 syslog 守护进程(我个人更喜欢 Syslog-NG,但 rsyslog 也可以很好地工作),并将其直接与您的脚本绑定。您的脚本不需要在新事件进入时完成所有跟踪工作,您的脚本只需处理
stdin
,并且 syslog 守护进程会在新日志进入时自动将其发送到您的脚本。我使用过此方法多次成功。我的第二个选择是让更高级别的 Perl 模块承担尽可能多的繁重工作。我要寻找的第一个地方是
File::Tail
。和以前一样,这使您摆脱了观看文件本身的问题,并让您专注于处理。I'm going to try to address your root problem, even though it doesn't exactly answer your question.
I think using inotify is too low-level a way of resolving this. If I were you, I'd be looking at a higher-level solution that frees you from the details of finding new events, and lets you concentrate on processing the log events. No need to reinvent the wheel when there's a bunch of good ones already available.
My first choice would be to use a modern syslog daemon (personally I prefer Syslog-NG, but rsyslog would work well enough, too), and tie that directly to your script. Instead of your script going through all the work of tracking when new events come in, your script just processes
stdin
, and the syslog daemon automatically sends new logs to your script as they come in. I've used this method successfully on numerous occasions.My second choice would be to let a higher-level Perl module do as much of the heavy lifting as possible. The first place I'd look for that would be
File::Tail
. Like before, this frees you from the problems of watching the file itself, and lets you concentrate on the processing.查看 CPAN 上的 Inotify 并尝试一下使用回调来检查所有错误:
此外,您正在监视文件上的几乎每个事件。我只会监视修改事件或一小部分事件,以查看问题是否仍然存在。
Looking at Inotify on CPAN and have you tried it with the callback to check all the errors:
Also, you are watching for almost every event on the file. I'd only watch for modification events or a smaller subset of events to see if the problem still existed.