Frage Ermitteln, ob die Datei gerade geschrieben wird?


Ich muss einen automatisierten Prozess (über 1 min Cron-Skript) bereitstellen, die nach tar-Dateien in einem bestimmten Verzeichnis sucht. Wenn eine TAR-Datei gefunden wird, wird sie an den entsprechenden Speicherort entpackt und anschließend wird 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 Problem, mit dem ich rechnen möchte: Wenn es> 1 Minute dauert, bis die TAR-Datei auf den Server kopiert wird und das Cron-Skript einmal pro Minute ausgeführt wird, sieht es die .tar.gz-Datei und versucht es Entpacken Sie es, obwohl die TAR-Datei noch in Bearbeitung ist.

Gibt es einen Weg (über Bash-Befehle) zu testen, ob gerade in eine Datei geschrieben wird, oder ob es sich nur um eine Teildatei handelt?

Eine Alternative, an die ich gedacht habe, war, die Datei als eine andere Dateierweiterung (wie .tar.gz.part) und dann in umbenannt .tar.gz nachdem die Übertragung abgeschlossen ist. Aber ich dachte mir, ich würde versuchen herauszufinden, ob es einfach einen Weg gibt, um zu bestimmen, ob die Datei als Ganzes in der Befehlszeile steht ... Irgendwelche Hinweise?


21
2017-08-08 16:03


Ursprung


Wie genau wird die Datei übertragen? Zum Beispiel, rsync verwendet einen temporären Dateinamen während der Übertragung (standardmäßig) und nur nach dem Die Datei wird vollständig übertragen und in den tatsächlichen Dateinamen umbenannt. - Piskvor


Antworten:


Sie befinden sich auf dem richtigen Weg, das Umbenennen der Datei ist ein atomarer Vorgang, daher ist das Umbenennen nach dem Upload einfach, elegant und nicht fehleranfällig. Ein anderer Ansatz, den ich mir vorstellen kann, ist zu verwenden lsof | grep filename.tar.gz um zu überprüfen, ob auf die Datei von einem anderen Prozess zugegriffen wird.


8
2017-08-08 16:08



(lsof filename.tar.gz ist effizienter und genauer als lsof | grep filename.tar.gz) - Rich


Ihre beste Wette ist zu verwenden lsof um festzustellen, ob eine Datei von einem Prozess geöffnet wurde:

#  lsof -f -- /var/log/syslog
COMMAND   PID   USER   FD   TYPE DEVICE SIZE/OFF  NODE NAME
rsyslogd 1520 syslog    1w   REG  252,2    72692 16719 /var/log/syslog

Sie können nicht leicht sagen, ob es gerade geschrieben wird, aber wenn es geschrieben wird, MUSS es offen sein.


Edit: Lassen Sie uns das eigentliche Problem lösen, anstatt zu versuchen, die vorgeschlagene Lösung zu implementieren!

Verwenden Sie rsync, um die Datei zu übertragen:

○ → rsync -e ssh remote:big.tar.gz .

Auf diese Weise wird die Datei nicht über die vorhandene kopiert, sondern in eine temporäre Datei kopiert (.big.tar.gz.XXXXXX) bis die Übertragung abgeschlossen ist und dann an ihren Platz gebracht wurde.


12
2017-08-08 16:09





Der beste Weg dies zu tun ist zu verwenden Inkron ("Inotify Cron System"). Es ermöglicht Ihnen, ein zu setzen annotieren Achten Sie auf ein Verzeichnis, das Sie über Dateioperationen informiert. In diesem Fall sollten Sie das Verzeichnis nach einem close_write beobachten. Dadurch können Sie Ihren Befehl ausführen, sobald die Datei nach einem Schreibvorgang geschlossen wurde.


5
2017-08-08 16:36





Ein bisschen alt, aber die meisten Antworten verfehlen völlig den Punkt der Frage:

Aber ich dachte, ich würde versuchen herauszufinden, ob es einfach eine Möglichkeit gibt, zuerst festzustellen, ob die Datei vollständig in der Befehlszeile ist ...

Im Allgemeinen gibt es nicht. Sie haben einfach nicht genug Informationen, um das festzustellen.

Weil es bestimmt, dass die Datei ist geschlossen ist nicht das gleiche wie zu bestimmen, ob die Datei ist ganze. Zum Beispiel wird eine Datei "geschlossen", wenn die Verbindung während der Übertragung verloren geht.

Nur @ Alex Antwort hat das richtig gemacht. Und sogar er fiel auf zu benutzen lsof etwas.

Um festzustellen, ob die Datei vollständig übertragen wurde, werden mehr Daten benötigt. Sowie:

Eine Alternative, an die ich gedacht habe, war, die Datei als eine andere Dateierweiterung (wie .tar.gz.part) und dann in umbenannt .tar.gznachdem die Übertragung abgeschlossen ist.

Das ist eine sehr gute Möglichkeit zu kommunizieren, dass die Datei vollständig und erfolgreich übertragen wurde. Sie können Dateien auch von einem Verzeichnis in ein anderes verschieben, solange Sie sich im selben Dateisystem befinden. Oder lassen Sie den Absender eine leere senden filename.done Datei, um den Abschluss zu signalisieren.

Aber alle Methoden müssen darauf angewiesen sein, dass der Absender irgendwie signalisiert, dass die Übertragung erfolgreich abgeschlossen wurde. Weil nur der Absender diese Information hat.

Einige Dateiformate (z. B. PDFs) enthalten Daten, mit denen Sie feststellen können, ob die Datei vollständig ist. Aber Sie müssen die gesamte Datei öffnen und lesen, um es herauszufinden.

lsof wird Ihnen nur sagen, dass die Datei nicht mehr geöffnet ist - es wird Ihnen nicht sagen Warum es ist nicht mehr offen. Noch wird es dir sagen, wie groß die Datei sein soll.


3
2018-04-20 18:31



Ich kann das nicht genug verbessern. Guter Job, um das XY-Problem hier zu lösen. - Beefster


Es scheint, als könnte lsof erkennen, in welchem ​​Modus eine Datei geöffnet ist:

lsof -f -- a_file
COMMAND   PID  USER   FD   TYPE DEVICE SIZE/OFF     NODE NAME
cat     52391 bob    1w   REG    1,2       15 19545007 a_file

Siehst du, wo es 1w steht? Das bedeutet, dass die Nummer des Dateideskriptors 1 ist und der Modus w oder write lautet.


2
2017-07-26 02:57



Das FD Feld zeigt 3r für mich, wenn die Datei zum Lesen geöffnet ist. - Sopalajo de Arrierez