Просмотр нескольких файлов с inotify в perl

Мне нужно смотреть несколько файлов в 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 ответа

Решение

Один объект 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).

Похоже, вы выполняете проверки в последовательном режиме на том, что вы хотите, чтобы происходило параллельно. Вы либо захотите внедрить отдельный процесс, использовать потоки или интегрировать его с объектом POE.

Другой вариант, который может работать, а может и не работать для вашего приложения, состоит в том, чтобы установить для вашего tempdir что-то более конкретное и сохранить там все файлы, над которыми вы работаете, а затем просто просмотреть каталог в целом, для чего потребуется только 1 Inotify объект, если я читаю это право. (Я ничего не сделал с этим модулем, в частности, но у меня есть довольно хорошее представление о том, как он работает, подключая системные вызовы к файловой системе).

Другие вопросы по тегам