Ich beobachte Dateien mithilfe von inotify-Ereignissen auf Änderungen (wie es passiert, von Python aus, indem ich libc aufrufe).
Für einige Dateien während eines git clone
sehe ich etwas Seltsames: Ich sehe ein IN_CREATE
Ereignis, und ich sehe darüber, ls
dass die Datei Inhalt hat, aber ich sehe IN_MODIFY
oder nie IN_CLOSE_WRITE
. Dies verursacht Probleme, da ich IN_CLOSE_WRITE
auf die Dateien antworten möchte : insbesondere, um einen Upload des Dateiinhalts zu initiieren.
Die Dateien, die sich merkwürdig verhalten, befinden sich im .git/objects/pack
Verzeichnis und enden mit .pack
oder .idx
. Andere Dateien, die git erstellt, haben eine regelmäßigere IN_CREATE
-> IN_MODIFY
-> IN_CLOSE_WRITE
Kette (ich suche nicht nach IN_OPEN
Ereignissen).
Dies ist in Docker unter MacOS enthalten, aber ich habe Hinweise auf Docker unter Linux in einem Remote-System gesehen, sodass ich den Verdacht habe, dass der MacOS-Aspekt nicht relevant ist. Ich sehe dies, wenn ich zuschaue und mich git clone
im selben Docker-Container befinde.
Meine Fragen:
Warum fehlen diese Ereignisse in diesen Dateien?
Was kann man dagegen tun? Wie kann ich konkret auf den Abschluss von Schreibvorgängen in diese Dateien reagieren? Hinweis: Idealerweise möchte ich antworten, wenn das Schreiben "beendet" ist, um zu vermeiden, dass unnötig / (fälschlicherweise) "unfertiges" Schreiben hochgeladen wird.
Bearbeiten: Lesen von https://developer.ibm.com/tutorials/l-inotify/ Es sieht so aus, als ob das, was ich sehe, mit dem übereinstimmt, was ich sehe
- eine separate temporäre Datei mit Namen wie
tmp_pack_hBV4Alz
, die erstellt, geändert und geschlossen wird; - Zu dieser Datei wird ein fester Link mit dem endgültigen
.pack
Namen erstellt. - Der ursprüngliche
tmp_pack_hBV4Alz
Name wird gelöscht.
Ich denke, mein Problem, das versucht, inotify als Auslöser zum Hochladen von Dateien zu verwenden, reduziert sich dann darauf, zu bemerken, dass die .pack
Datei ein fester Link zu einer anderen Datei ist, und in diesem Fall hochzuladen?
Antworten:
So beantworten Sie Ihre Frage für
git
2.24.1 unter Linux 4.19.95 separat:Sie sehen
IN_MODIFY
/IN_CLOSE_WRITE
events nicht, dagit clone
immer versucht wird, feste Links für Dateien im.git/objects
Verzeichnis zu verwenden. Beim Klonen über das Netzwerk oder über Dateisystemgrenzen hinweg werden diese Ereignisse erneut angezeigt.Um Änderungen an Hardlinks abzufangen, müssen Sie einen Handler für das folgende inotify-
CREATE
Ereignis einrichten und diese Links verfolgen. Bitte beachten Sie, dass eine einfacheCREATE
Datei auch bedeuten kann, dass eine nicht leere Datei erstellt wurde. Dann müssen Sie fürIN_MODIFY
/IN_CLOSE_WRITE
zu einer der Dateien dieselbe Aktion auch für alle verknüpften Dateien auslösen. Natürlich müssen Sie diese Beziehung auch für dasDELETE
Ereignis entfernen .Ein einfacherer und robusterer Ansatz wäre wahrscheinlich, alle Dateien regelmäßig zu hashen und zu überprüfen, ob sich der Inhalt einer Datei geändert hat.
Korrektur
Nach Überprüfung der
git
Quellcode eng und laufengit
mitstrace
, fand ich , dass diegit
Verwendung Memory - Mapped - Dateien, aber vor allem für das Lesen von Inhalten der Fall ist. Sehen Sie, deren Verwendungxmmap
immer nur mit aufgerufen wirdPROT_READ
. . Daher ist meine vorherige Antwort unten NICHT die richtige Antwort. Trotzdem möchte ich es zu Informationszwecken hier behalten:Sie sehen nicht ,
IN_MODIFY
Ereignisse , weilpackfile.c
Anwendungenmmap
für Access - Datei undinotify
Änderungen nicht für berichtenmmap
ed - Dateien.Aus der inotify-Manpage :
quelle
IN_CLOSE_WRITE
, was meiner Meinung nach beim Schließen einer Datei, in die geschrieben wurde, immer noch ausgelöst wirdmmap
, da die Datei in einem Schreibmodus hätte geöffnet werden müssen.mmap
eine Datei verwenden, kann es zu Abweichungen kommen . Sie können beispielsweise weiterhin in einen geschlossenen Dateideskriptor schreiben, wenn Sie die Datei im Speicher zugeordnet haben.CLOSE_WRITE_CLOSE
gerade, wenn ich dasclose
undmunmap
am Ende entferne . Müssen dann tiefer in die eigentliche Git-Implementierung eintauchen ..inotifywait
undgit clone
(2.24.1) bekomme ich einOPEN
->CLOSE_NOWRITE,CLOSE
für die*.idx
Dateien. Vielleicht haben Sie vergessen, einen Handler einzurichtenCLOSE_NOWRITE,CLOSE
? Hinweis: Sie erhalten eine,*NOWRITE*
da alle Schreibvorgänge über den zugeordneten Speicher ausgeführt wurden.CLOSE_NOWRITE
: Das Problem ist, dass ich es nicht seheIN_CLOSE_WRITE
, und ich möchte auf "Änderungen" der Datei reagieren, um einen Upload auszulösen, aber "Lesevorgänge" ignorieren. Beachten Sie, ich denke im Moment, dass die Einschränkung von mmap + inotify ein bisschen wie ein roter Hering ist. Ich denke, das Problem ist, dass die.pack
/.idx
-Dateien anfänglich als feste Links zu einer anderen Datei erstellt werden und daher nur ausgelöst werdenIN_CREATE
(und dasOPEN
->CLOSE_NOWRITE
passiert später, wenn Git die Dateien tatsächlich liest).Ich kann spekulieren, dass Git die meiste Zeit Atomic File Updates verwendet, die wie folgt durchgeführt werden:
mktemp
-style).rename(2)
d-d über der ursprünglichen; Diese Operation garantiert, dass jeder Beobachter, der versucht, die Datei unter seinem Namen zu öffnen, entweder den alten oder den neuen Inhalt erhält.Solche Aktualisierungen werden
inotify(7)
alsmoved_to
Ereignisse angesehen, da eine Datei in einem Verzeichnis "wieder angezeigt" wird.quelle
IN_MOVED_FROM
undIN_MOVED_TO
Ereignisse. Ich sehe dies jedoch nicht für die.pack
und.idx
DateienBasierend auf dieser akzeptierten Antwort würde ich annehmen, dass es einen Unterschied in den Ereignissen geben könnte, die auf dem verwendeten Protokoll basieren (dh ssh oder https).
Beobachten Sie dasselbe Verhalten, wenn Sie das Klonen aus dem lokalen Dateisystem mit der
--no-hardlinks
Option überwachen ?Ihr beobachtetes Verhalten beim Ausführen des Experiments sowohl auf einem Linux- als auch auf einem Mac-Host beseitigt wahrscheinlich dieses offene Problem, das die Ursache https://github.com/docker/for-mac/issues/896 ist, aber nur für den Fall, dass es hinzugefügt wird.
quelle
Es gibt eine andere Möglichkeit (vom Menschen inotifizieren):
Und während
git clone
kann schweren Ereignisablauf erzeugt, kann das passieren.So vermeiden Sie dies:
quelle
Vielleicht haben Sie den gleichen Fehler gemacht, den ich vor Jahren gemacht habe. Ich habe inotify nur zweimal verwendet. Beim ersten Mal hat mein Code einfach funktioniert. Später hatte ich diese Quelle nicht mehr und fing wieder an, aber diesmal fehlten mir Ereignisse und ich wusste nicht warum.
Es stellt sich heraus, dass ich beim Lesen eines Ereignisses wirklich eine kleine Menge von Ereignissen gelesen habe. Ich analysierte den, den ich erwartet hatte und dachte, das war es, das war alles. Schließlich stellte ich fest, dass die empfangenen Daten mehr enthalten, und als ich einen kleinen Code hinzufügte, um alle Ereignisse zu analysieren, die von einem einzelnen Lesevorgang empfangen wurden, gingen keine weiteren Ereignisse verloren.
quelle