在perl中使用inotify查看多个文件

在perl中使用inotify查看多个文件,perl,file-io,inotify,Perl,File Io,Inotify,我需要在Perl中查看多个文件,我正在使用。但是我遇到了一个问题,第一个被监视的文件需要修改和点击,然后是第二个,然后是第一个等等 例如,如果第二个文件在第一个文件之前更改,则不会触发输出,或者如果第一个文件在一行中被触发两次,而第二个文件在两次触发之间没有被触发 这是我正在使用的代码中存在此问题的部分 my $inotify = new Linux::Inotify2; my $inotify2 = new Linux::Inotify2; $inotify->watch ("/tmp/

我需要在Perl中查看多个文件,我正在使用。但是我遇到了一个问题,第一个被监视的文件需要修改和点击,然后是第二个,然后是第一个等等

例如,如果第二个文件在第一个文件之前更改,则不会触发输出,或者如果第一个文件在一行中被触发两次,而第二个文件在两次触发之间没有被触发

这是我正在使用的代码中存在此问题的部分

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);
    }
  }
}
my$inotify=newlinux::Inotify2;
my$inotify2=新Linux::inotify2;
$inotify->watch(“/tmp/rules.txt”,在_MODIFY中);
$inotify2->watch(“/tmp/csvrules.out”,IN_MODIFY);
而(){
my@events=$inotify->read;
除非(@events>0){
打印“读取错误:$!”;
最后;
}
foreach$mask(@events){
printf“mask\t%d\n”,$mask;
打开(WWWRULES,“/tmp/rules.txt”);
我的@lines=;
foreach$行(@行){
@事物=分割(/,/,$行);
addrule(@things[0]、@things[1]、@things[2]、@things[3]、trim(@things[4]);
打印“打印:@things[0]、@things[1]、@things[2]、@things[3]、@things[4]”;
关闭(WWWRULES);
打开(WWWRULES,“>/tmp/rules.txt”);
关闭(WWWRULES);
}
}
my@events2=$inotify2->read;
除非(@events2>0){
打印“读取错误:$!”;
最后;
}
foreach$mask(@events){
printf“mask\t%d\n”,$mask;
打开(SNORTRULES,“/tmp/csvrules.out”);
我的@lines2=;
foreach$line2(@lines2){
@things2=拆分(/,/,$line2);
addrule(“INPUT”、@things2[0]、@things2[1]、@things2[2]、trim(@things2[3]);
打印“打印:输入,@things2[0]、@things2[1]、@things2[2]、@things2[3]”;
关闭(通气管);
打开(SNORTRULES,“>/tmp/csvrules.out”);
关闭(通气管);
}
}
}
理想情况下,我想看3个文件,但由于我无法让2个工作,这似乎是一个没有意义的阶段


谢谢你的帮助

您似乎在对希望并行发生的事情进行串行检查。您可能想要分叉一个单独的进程,使用线程,或者将其与POE对象集成


另一种可能适用于您的应用程序,也可能不适用于您的应用程序的方法是将tempdir设置为更具体的值,并将您正在处理的所有文件都保存在其中,然后只作为一个整体查看目录,如果我读对了,那么只需要1个inotify对象。(我没有对这个模块做任何特别的操作,但是我非常清楚它是如何通过将系统调用挂接到文件系统来工作的)。

一个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
)。

如果我查看一个目录,我可以确定该目录中的哪个文件被修改了,以便根据哪个文件被修改来采取行动吗?我不是100%确定,但看来你应该能做到。除非我弄错了,否则仍然应该为目录中的文件引发IN_访问事件。实际上,句柄对监视的数量是有限制的。此限制在/proc/sys/fs/inotify/max\u user\u中设置