Frage

Ich muss mehrere Dateien in Perl ansehen, und ich benutze Linux :: Inotify2. Ich stoße jedoch insofern auf ein Problem, in dem die erste zu beobachtete Datei geändert und gedrückt werden muss, dann die zweite, dann die erste usw. usw. usw.

Wenn beispielsweise die zweite Datei vor der ersten geändert wird, wird sie nicht ausgelöst, oder wenn die erste zweimal hintereinander ausgelöst wird, ohne dass der zweite dazwischen ausgelöst wird.

Dies ist der Codeabschnitt, den ich verwende, der dieses Problem hat.

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

Idealerweise möchte ich 3 Dateien ansehen, aber da ich 2 nicht arbeiten kann, scheint es in dieser Phase ein wenig sinnlos zu sein.

Danke für jede Hilfe!

War es hilfreich?

Lösung

Ein einzelnes Inotify -Objekt kann eine beliebige Anzahl von Uhren verarbeiten. Dies ist einer der Vorteile der Inotify gegenüber dem älteren und jetzt veralteten Dnotify. Sie sollten also sagen:

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

Dann können Sie sehen, welche Uhr durch Überprüfung der ausgelöst wurde fullname Eigenschaft des Ereignisobjekts:

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

Das große Problem besteht darin, dass Ihr Code die gleichen Dateien ändert, die Sie nach Änderungen beobachten. Wann /tmp/rules.txt wird modifiziert, öffnen Sie es, lesen es und schneiden dann ab, was einen weiteren Modifikationshinweis auslöst und den gesamten Prozess erneut starten. Im Allgemeinen ist dies schwer ohne Rennbedingungen zu lösen, aber in Ihrem Fall sollten Sie in der Lage sein, nur nach einer leeren Datei zu suchen (next if -z $event->fullname).

Andere Tipps

Sie scheinen Schecks in der Serie über etwas durchzuführen, das Sie parallel machen möchten. Entweder möchten Sie einen separaten Prozess auslassen, Threading verwenden oder in ein PoE -Objekt integrieren.

Eine andere Option, die möglicherweise für Ihre Anwendung funktioniert oder nicht, besteht darin, Ihr Tempdir auf etwas Spezifischeres zu setzen und alle Dateien zu behalten, an denen Sie dort arbeiten, und beobachten Sie dann einfach das Verzeichnis als Ganzes, was dann nur 1 erfordern würde Objekt infotieren, wenn ich dieses Recht lese. (Ich habe nichts mit diesem Modul gemacht, aber ich habe eine ziemlich gute Vorstellung davon, wie es funktioniert, indem ich Syscalls an das Dateisystem anschließt.)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top