Warum werden inotifizierte Ereignisse mehrmals ausgelöst?

13

Diese Frage ergibt sich aus einer anderen, die ich bei Stackoverflow gestellt hatte . Ich verwende Watcher - die gleichen Probleme treten auch bei Incron auf -, um einen Ordner und seine untergeordneten Ordner auf Änderungen zu überwachen und diese Änderungen stillschweigend in Dropbox zu verwerfen.

Ich verfolge das write_closeEreignis IN_CLOSE_WRITEzu diesem Zweck. Ursprünglich habe ich das modifyEreignis beobachtet, also IN_MODIFY. Während dies funktionierte, stellte ich fest, dass es beim Schreiben großer Dateien mehr als einmal ausgelöst wurde. Das klang fair und ich wechselte zu, IN_CLOSE_WRITEda ich der Meinung war, dass es angemessen war anzunehmen, dass es für eine bestimmte Datei nur einmal vorkommen würde.

Dies ist jedoch nicht der Fall. Selbst für eine sehr kleine Textdatei - nur ein Zeichen -, die in Nano erstellt wurde, tritt das Ereignis zweimal auf. Bestenfalls kann dies zu unnötigem Datenverkehr führen, wenn dieselbe Datei zweimal mit Dropbox synchronisiert wird. In meinem eigenen Fall führt dies zu einer Katastrophe, da ich beim ersten Ereignis die Synchronisierung durchführe und dann die serverseitige Datei lösche. Das Ergebnis - beim zweiten Ereignis wird die Dropbox-Nebendatei zu einer 0-Byte-Datei.

Ich beschäftige mich jetzt damit, indem ich mein Synchronisationsskript für 10s in den Ruhezustand versetze, bevor ich etwas anderes tue, und dann überprüfe ich, ob die fragliche Datei noch vorhanden ist, bevor ich die Dropbox-Synchronisation versuche. Dies funktioniert, weil bei der zweiten Iteration die Datei fehlt und das Skript gerade beendet wird.

Das klingt bestenfalls hackisch. Vielleicht kein schlechter Hack, aber ich würde es vorziehen zu verstehen - warum tritt das IN_CLOSE_WRITEEreignis überhaupt mehr als einmal auf?


Einige zusätzliche Informationen

  • Stellen Sie sicher, dass nicht mehrere Watcher-Instanzen ausgeführt werden.

Ausgabe von ps ax|grep watcher.py

23880 ?        Sl     0:01 python /usr/local/bin/watcher.py restart
24977 pts/0    S+     0:00 grep --color=auto watcher.py

Das Dateisystem ist ext4. Ich sollte erwähnen, dass ich genau das gleiche Problem mit Incron angetroffen habe. Ich starte den Watcher-Daemon über ein Batch-Skript, das über ausgeführt wird /etc/rc2.d. Incron OTH startet über die Standardinstallation, ohne dass ich irgendwelche Probleme damit habe apt-get install incron.


Das Wesentliche meiner watcher.iniDatei ist unten dargestellt.

[DEFAULT]
logfile=/var/log/watcher.log
pidfile=/var/run/watcher.pid

[job1]
watch=/path/to/watch

events=write_close
excluded=
recursive=true
autoadd=true

command=/home/datastore.php $filename

Ich habe das datastore.phpSkript auf das Nötigste reduziert, um sicherzustellen, dass es zweimal gestartet wird, ohne dass mein unordentlicher Dropbox-Upload und Quellcode gelöscht werden.

#! /usr/bin/php
<?php
file_put_contents('/tmp/watcher',$argv[1],FILE_APPEND);

?>

Ich habe dann eine kleine Datei auf dem fraglichen Pfad angelegt und dann geprüft /tmp/watcher. Das Problem besteht weiterhin - die Datei enthält weiterhin zwei aufeinanderfolgende Einträge für $argv[1].

DroidOS
quelle
1
Ich habe viele Variationen ausprobiert, kann Ihr Problem jedoch nicht mit mehreren IN_CLOSE_WRITE-Bränden duplizieren. Alles, was ich getan habe, verursacht eine einzige Inotify-Ausgabe. Ich werde weiterhin Dinge versuchen. Aber bisher nur Fragen. Welches Dateisystem? Ext4? Andere?
Lornix
@ Lornix - Bitte beachten Sie die Änderungen an meiner Frage. Das Dateisystem ist ext4und ich bin mir ziemlich sicher, dass nicht zwei Instanzen von Watcher ausgeführt werden. Ich bin mit Incron auf dasselbe Problem gestoßen.
DroidOS
Sie sagten: "Ich führe die Synchronisierung durch und lösche dann die serverseitige Datei." Löst dieses Löschen das zweite Ereignis aus? Können Sie deaktivierendelete Routine und es erneut versuchen?
Germar
@ Germar - siehe die Bearbeitung meiner Frage. Selbst wenn das Synchronisierungsskript keine echte Synchronisierung ausführt und unlinkdas Problem nicht auftritt , bleibt es bestehen
DroidOS
Leider kann ich das Problem auf keinem meiner Computer reproduzieren. Ich bekomme ein Ereignis, nicht mehr. Es handelt sich um etwas anderes, nicht Erwähntes. Haben Sie Antivirus installiert? so etwas?
Lornix

Antworten:

1

Ich bin nicht sicher, aber höchstwahrscheinlich schreibt die erste write_close Dateiattribute, wie die Erstellungszeit, und erst danach werden die tatsächlichen Daten geschrieben. Tatsächlich erstellt rsync eine temporäre Datei, und wenn alles erledigt ist, verschiebt es die temporäre Datei in die eigentliche Datei im selben Ordner, so dass es einfach zu überwachen ist, wenn Sie rsync verwenden. Das Verschieben ist eine atomare Operation. Auf der anderen Seite gibt es etwas, das man in inotify erschossen hat, wahrscheinlich das man damit bei der ersten Änderungsnachricht etwas auslösen kann, und wie Sie vorgeschlagen haben, für eine angemessene Zeit vor dem Start der Operation schlafen zu gehen. Ich grabe das jetzt und werde es aktualisieren, wenn ich etwas Neues finde. /superuser/1133642/traceing-the-moment-when-file-is-complete-copied-to-samba-share-with-inotify

Edik Mkoyan
quelle
Vielleicht haben Sie hier etwas ganz Gültiges gefunden. Es wird einige Nachforschungen erfordern. Danke für den Tipp. Ich werde zurückschreiben, falls ich finde, dass dies irgendwie ein Problem ist.
DroidOS
Ich glaube nicht, dass ATTRIB irgendetwas zur Datei selbst hinzufügt, ich habe mich geirrt.
Edik Mkoyan
0

Ich habe nicht genug Mitarbeiter, um dies als Kommentar zu posten, aber sind Sie sicher, dass keine temporären, möglicherweise ausgeblendeten Dateien erstellt werden? Ich hatte ein ähnliches Problem beim inotifywaitmehrmaligen Auslösen, aber mir wurde klar, dass vim beim Bearbeiten eine .swp-Datei erstellen würde, die beim Schließen ein Ereignis auslösen würde. Es würde auch das Abschlussereignis aus der Originaldatei übernehmen.

Es hört sich so an, als würden Sie feststellen, dass ein Ereignis mehrere Dateien auf dieselbe Datei abfeuert, was ich nicht reproduzieren konnte - dies würde nur einmal für die temporäre Datei und einmal für das Original geschehen.

Ich habe einen Schnelltest mit Nano versucht und glaube nicht, dass es überhaupt eine temporäre Datei erstellt (zumindest für die wenigen Zeichen), aber gibt es noch etwas in Ihrem Setup, das sich auf ein ähnliches Verhalten stützen könnte?

neocpp
quelle
danke für eure vorschläge. Selbst wenn ich mit Nano eine sehr einfache 1-Byte-Datei erstelle - oder wenn ich nur ein einzelnes Zeichen von der Konsole in eine Datei umleite - stieß ich auf das inotify multiple Problem. Die "Lösung", die ich in meiner ursprünglichen Frage skizziert habe, hält mich vorerst am Laufen. Langfristig ist dies jedoch die einzige Lösung, die ich brauche, um meinen Server von Grund auf neu zu erstellen, um festzustellen, wann der Fehler auftritt - meine Einrichtung mit Incron, Watcher (übrigens, als ich gerade Incron hatte), MariaDB, Nginx, Redis, Memcached ... ist nicht gerade "einfach".
DroidOS
Überprüfen Sie auf jeden Fall, ob Sie denselben Ordner nicht zweimal überwachen. Wenn nicht, dann geschieht dies zum Beispiel, wenn ich eine Datei über den os x samba-Client auf die Samba-Freigabe kopiere. Create, close_write, delete, create, close_write Wenn ich das mit einem Windows-Client mache, sieht es vernünftiger aus, create, write_close und nichts weiter. Ich löse mein Problem, indem ich die erste Änderung der Datei mit diesem Verzeichnis IN_MODIFY, IN_ONESHOT / überwache. sleep someTime befehle oneshot erledigt das ding.
Edik Mkoyan