我需要使用Perl和Linux::Inotify2处理大型(~100s)系统日志消息。
我写了一个连续生成日志消息的测试脚本。要处理事件,我的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脚本正在丢失事件。
我也没有看到任何溢出消息。
我如何确保即使我的处理速度很慢,也不会丢失消息。换句话说,如何定义可暂时存储消息的“缓冲区”?
答案 0 :(得分:1)
我将尝试解决您的根本问题,即使它没有完全回答您的问题。
我认为使用inotify太低级了解决这个问题。如果我是你,我会看一个更高级别的解决方案,让你从发现新事件的细节中解放出来,让你专注于处理日志事件。当有一堆好的已经可用时,无需重新发明轮子。
我的第一选择是使用现代的syslog守护进程(我个人更喜欢Syslog-NG,但rsyslog也可以运行得很好),并将其直接与你的脚本联系起来。您的脚本只会处理stdin
而不是您的脚本完成所有跟踪工作,而脚本只会处理File::Tail
,并且syslog守护程序会在脚本进入时自动将新日志发送到您的脚本。我已成功使用此方法在很多场合。
我的第二选择是让更高级别的Perl模块尽可能多地完成繁重的工作。我要找的第一个地方是{{1}}。像以前一样,这使您免于观察文件本身的问题,并让您专注于处理。
答案 1 :(得分:0)
查看Inotify on CPAN并尝试使用回调检查所有错误:
$inotify->watch ("/etc/passwd", IN_ACCESS | IN_MODIFY, sub {
my $e = shift;
print "$e->{w}{name} was accessed\n" if $e->IN_ACCESS;
print "$e->{w}{name} was modified\n" if $e->IN_MODIFY;
print "$e->{w}{name} is no longer mounted\n" if $e->IN_UNMOUNT;
print "events for $e->{w}{name} have been lost\n" if $e->IN_Q_OVERFLOW;
});
此外,您正在观看文件中的几乎所有事件。我只会观察修改事件或较小的事件子集,以查看问题是否仍然存在。