Why is inotify losing events?

孤街浪徒 提交于 2021-02-08 21:19:21

问题


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?


回答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.




回答2:


Looking at Inotify on CPAN and have you tried it with the callback to check all the errors:

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

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.



来源:https://stackoverflow.com/questions/8454827/why-is-inotify-losing-events

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!