4

我需要使用 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 脚本正在丢失事件。

我也没有看到任何溢出消息。

我如何确保即使我的处理速度很慢,我也不会丢失消息。换句话说,我如何定义可以临时存储消息的“缓冲区”?

4

2 回答 2

1

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.

于 2012-04-01T20:40:28.263 回答
0

查看CPAN 上的 Inotify并尝试使用回调检查所有错误:

 $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;
  });

此外,您正在关注文件中的几乎所有事件。我只会关注修改事件或事件的较小子集,以查看问题是否仍然存在。

于 2012-04-01T11:37:13.503 回答