在perl中使用inotify监视多个文件

时间:2011-03-15 18:18:06

标签: perl file-io inotify

我需要在Perl中观看多个文件,而我正在使用Linux::Inotify2。但是我遇到了一个问题,即被监视的第一个文件需要被修改和命中,然后是第二个,然后是第一个等等

例如,如果第二个文件在第一个文件之前被更改,它将不会被触发,或者如果第一个文件连续两次触发而没有第二个文件被触发。

这是我正在使用的具有此问题的代码部分。

my $inotify = new Linux::Inotify2;
my $inotify2 = new Linux::Inotify2;
$inotify->watch ("/tmp/rules.txt", IN_MODIFY);
$inotify2->watch ("/tmp/csvrules.out", IN_MODIFY);

while () {
  my @events = $inotify->read;
  unless (@events > 0){
    print "read error: $!";
    last ;
  }

  foreach $mask (@events) {
    printf "mask\t%d\n", $mask;

    open (WWWRULES, "/tmp/rules.txt");

    my @lines = <WWWRULES>;
    foreach $line (@lines) {
      @things = split(/,/, $line);
      addrule(@things[0], @things[1], @things[2], @things[3], trim(@things[4]));
      print "PRINTING: @things[0], @things[1], @things[2], @things[3], @things[4]";
      close (WWWRULES);
      open (WWWRULES, ">/tmp/rules.txt");
      close (WWWRULES);
    }
  }

  my @events2 = $inotify2->read;
  unless (@events2 > 0){
    print "read error: $!";
    last ;
  }
  foreach $mask (@events) {
    printf "mask\t%d\n", $mask;
    open (SNORTRULES, "/tmp/csvrules.out");

    my @lines2 = <SNORTRULES>;
    foreach $line2 (@lines2) {
      @things2 = split(/,/, $line2);
      addrule("INPUT", @things2[0], @things2[1], @things2[2], trim(@things2[3]));
      print "PRINTING: INPUT, @things2[0], @things2[1], @things2[2], @things2[3]";

      close (SNORTRULES);
      open (SNORTRULES, ">/tmp/csvrules.out");
      close (SNORTRULES);
    }
  }
}

理想情况下,我想观看3个文件,但由于我无法完成2个工作,所以在这个阶段似乎有点无意义。

感谢您的帮助!

2 个答案:

答案 0 :(得分:9)

单个inotify对象可以处理任意数量的手表。这是inotify相对于旧版本和现在过时的dnotify的优势之一。所以你应该说:

my $inotify = Linux::Inotify2->new;
$inotify->watch("/tmp/rules.txt", IN_MODIFY);
$inotify->watch("/tmp/csvrules.out", IN_MODIFY);

然后,您可以通过检查事件对象的fullname属性来查看触发了哪个监视:

while () {
  my @events = $inotify->read;
  unless (@events > 0){
    print "read error: $!";
    last ;
  }

  foreach my $event (@events) {
    print $event->fullname . " was modified\n" if $event->IN_MODIFY;
  }
}

最大的问题是您的代码正在修改您正在观看修改的相同文件。修改/tmp/rules.txt时,打开它,读取它,然后截断它,这会触发另一个修改通知,重新开始整个过程​​。一般来说,如果没有竞争条件,这很难解决,但在您的情况下,您应该只能检查一个空文件(next if -z $event->fullname)。

答案 1 :(得分:0)

您似乎正在对要并行发生的事情进行连续检查。您要么要分叉一个单独的进程,使用线程,要么将它与POE对象集成。

另一个可能适用于您的应用程序的选项是将您的tempdir设置为更具体的内容,并将您正在处理的所有文件保存在那里,然后只查看整个目录,然后只需要1个inotify对象,如果我正在读这个权利。 (我没有特别对这个模块做过任何事情,但是通过将系统调用挂钩到文件系统,我对它的工作原理非常了解。)