Ich muss einen automatisierten Prozess (über ein 1-minütiges Cron-Skript) bereitstellen, der nach TAR-Dateien in einem bestimmten Verzeichnis sucht. Wenn eine TAR-Datei gefunden wird, wird sie an der entsprechenden Stelle nicht geteert und dann die TAR-Datei gelöscht.
Die tar-Dateien werden automatisch über SSH von einem anderen Server auf diesen Server kopiert. In einigen Fällen sind die TAR-Dateien extrem groß und enthalten viele Dateien.
Das erwartete Problem: Wenn das Kopieren der TAR-Datei auf den Server länger als 1 Minute dauert und das Cron-Skript einmal pro Minute ausgeführt wird, wird die Datei .tar.gz angezeigt und versucht, dies zu tun Entpacken Sie es, obwohl die TAR-Datei noch geschrieben wird.
Gibt es eine Möglichkeit (über Bash-Befehle) zu testen, ob eine Datei gerade geschrieben wird oder ob es sich nur um eine Teildatei usw. handelt?
Als Alternative habe ich mir überlegt, die Datei als andere Dateierweiterung (wie .tar.gz.part
) zu kopieren und .tar.gz
nach Abschluss der Übertragung in umzubenennen. Aber ich dachte, ich würde versuchen herauszufinden, ob es einfach eine Möglichkeit gibt, festzustellen, ob die Datei in der Befehlszeile vollständig ist ... Irgendwelche Hinweise?
rsync
verwendet einen temporären Dateinamen während der Übertragung (Standard), und nur , nachdem die Datei vollständig übertragen wird, benennt es um die tatsächlichen Dateinamen.Antworten:
Sie sind auf dem richtigen Weg, das Umbenennen der Datei ist eine atomare Operation, daher ist das Umbenennen nach dem Hochladen einfach, elegant und nicht fehleranfällig. Ein anderer Ansatz, den ich mir vorstellen kann, besteht darin,
lsof | grep filename.tar.gz
zu überprüfen, ob auf die Datei von einem anderen Prozess zugegriffen wird.quelle
lsof filename.tar.gz
ist effizienter und genauer alslsof | grep filename.tar.gz
)Am besten stellen Sie
lsof
fest, ob eine Datei von einem der folgenden Prozesse geöffnet wurde:Man kann nicht leicht sagen, ob es gerade geschrieben wird, aber wenn es geschrieben wird, MUSS es offen sein.
Bearbeiten: Lassen Sie uns das eigentliche Problem hier lösen, anstatt zu versuchen, die vorgeschlagene Lösung zu implementieren!
Verwenden Sie rsync, um die Datei zu übertragen:
Auf diese Weise wird die Datei nicht über die vorhandene kopiert, sondern in eine temporäre Datei (
.big.tar.gz.XXXXXX
) kopiert, bis die Übertragung abgeschlossen ist, und dann an ihren Platz verschoben.quelle
Ein bisschen alt, aber die meisten Antworten verfehlen den Punkt der Frage völlig:
Im Allgemeinen gibt es nicht. Sie haben einfach nicht genug Informationen, um das festzustellen.
Das Feststellen, dass die Datei geschlossen ist, ist nicht dasselbe wie das Feststellen, ob die Datei vollständig ist . Beispielsweise wird eine Datei "geschlossen", wenn die Verbindung während der Übertragung unterbrochen wird.
Nur die Antwort von @ Alex stimmte. Und selbst er verliebte sich in
lsof
etwas.Um festzustellen, ob die Datei vollständig übertragen wurde, sind weitere Daten erforderlich. Sowie:
Auf diese Weise können Sie problemlos mitteilen, dass die Datei vollständig und erfolgreich übertragen wurde. Sie können auch Dateien von einem Verzeichnis in ein anderes verschieben, solange Sie sich im selben Dateisystem befinden. Oder lassen Sie den Absender eine leere
filename.done
Datei senden , um die Fertigstellung zu signalisieren.Alle Methoden müssen sich jedoch darauf verlassen, dass der Absender signalisiert, dass die Übertragung erfolgreich abgeschlossen wurde. Weil nur der Absender diese Informationen hat.
Einige Dateiformate (z. B. PDF-Dateien) enthalten Daten, anhand derer Sie feststellen können, ob die Datei vollständig ist. Sie müssen jedoch so ziemlich die gesamte Datei öffnen und lesen, um dies herauszufinden.
lsof
wird Ihnen nur mitteilen, dass die Datei nicht mehr geöffnet ist - es wird Ihnen nicht mitgeteilt, warum sie nicht mehr geöffnet ist. Sie erfahren auch nicht, wie groß die Datei sein soll.quelle
Am besten verwenden Sie dazu incron ("inotify cron system"). Sie können eine Inotify- Überwachung für ein Verzeichnis festlegen , die Sie dann über Dateivorgänge benachrichtigt. In diesem Fall sollten Sie das Verzeichnis auf close_write überwachen. Auf diese Weise können Sie Ihren Befehl ausführen, sobald die Datei nach einem Schreibvorgang geschlossen wurde.
quelle
Anscheinend kann lsof erkennen, in welchem Modus eine Datei geöffnet ist:
Sehen Sie, wo steht 1w? Das bedeutet, dass die Dateideskriptornummer 1 und der Modus w oder write ist.
quelle
FD
Feld zeigt3r
mir, wann die Datei zum Lesen geöffnet ist.Mit
inotifywait
können Sie das erreichen, wonach Sie suchen - Sie können warten, bis ein Dateischreibvorgang abgeschlossen ist, bevor Sie einen Befehl ausführen.Der folgende Befehl überwacht kontinuierlich einen Ordner nach neuen Dateien und führt den Befehl in der Schleife aus, wenn das Schreiben in die Datei abgeschlossen ist.
Weitere Konfigurationsoptionen finden Sie unter https://linux.die.net/man/1/inotifywatch
quelle