Lösung 1:
Am besten verwenden Sie 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 einfach sagen, ob gerade geschrieben wird, aber wenn geschrieben wird, MUSS es geöffnet sein.
Bearbeiten:Lassen Sie uns hier 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 (.big.tar.gz.XXXXXX
), bis die Übertragung abgeschlossen ist, und dann an ihren Platz verschoben.
Lösung 2:
Sie sind auf dem richtigen Weg, das Umbenennen der Datei ist ein atomarer Vorgang, daher ist das Umbenennen nach dem Hochladen einfach, elegant und nicht fehleranfällig. Ein anderer Ansatz, der mir einfällt, ist die Verwendung von lsof | grep filename.tar.gz
um zu überprüfen, ob auf die Datei von einem anderen Prozess zugegriffen wird.
Lösung 3:
Ein bisschen alt, aber die meisten Antworten gehen am Kern der Frage vorbei:
Aber ich dachte mir, ich würde versuchen, herauszufinden, ob es einfach eine Möglichkeit gibt, zuerst auf der Befehlszeile festzustellen, ob die Datei vollständig ist ...
Im Allgemeinen gibt es das nicht. Sie haben einfach nicht genügend Informationen, um das festzustellen.
Weil festgestellt wird, dass die Datei geschlossen ist ist nicht dasselbe wie festzustellen, ob die Datei ganz ist . Beispielsweise wird eine Datei "geschlossen", wenn die Verbindung während der Übertragung unterbrochen wird.
Nur die Antwort von @Alex hat das richtig gemacht. Und selbst er ist auf die Verwendung von lsof
hereingefallen etwas.
Um festzustellen, ob die Datei vollständig übertragen wurde, sind mehr Daten erforderlich. Zum Beispiel:
Eine Alternative, an die ich dachte, war, die Datei mit einer anderen Dateierweiterung zu kopieren (wie .tar.gz.part
) und dann in .tar.gz
umbenannt nachdem die Übertragung abgeschlossen ist.
Das ist eine perfekte Möglichkeit, um mitzuteilen, dass die Datei vollständig und erfolgreich übertragen wurde. Sie können auch Dateien von einem Verzeichnis in ein anderes verschieben, solange Sie im selben Dateisystem bleiben. Oder lassen Sie den Absender einen leeren filename.done
senden Datei, um den Abschluss zu signalisieren.
Alle Methoden müssen sich jedoch darauf verlassen, dass der Absender irgendwie signalisiert, dass die Übertragung erfolgreich abgeschlossen wurde. Weil nur der Absender diese Informationen hat.
Einige Dateiformate (z. B. PDFs) enthalten Daten, anhand derer Sie feststellen können, ob die Datei vollständig ist. Aber Sie müssen so ziemlich die gesamte Datei öffnen und lesen, um das herauszufinden.
lsof
wird Ihnen nur sagen, dass die Datei nicht mehr geöffnet ist - es wird Ihnen nicht warum sagen es ist nicht mehr geöffnet. Es sagt Ihnen auch nicht, wie groß die Datei sein soll.
Lösung 4:
Dazu verwenden Sie am besten incron ("inotify cron system"). Es ermöglicht Ihnen, eine Inotify-Überwachung für ein Verzeichnis festzulegen, die Sie dann über Dateioperationen benachrichtigt. In diesem Fall sollten Sie im Verzeichnis nach einem close_write Ausschau halten. Dadurch können Sie Ihren Befehl ausführen, sobald die Datei nach einem Schreibvorgang geschlossen wurde.
Lösung 5:
Es scheint, als ob lsof erkennen kann, 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
Sehen Sie, wo es 1w sagt? Das bedeutet, dass die Dateideskriptornummer 1 ist und der Modus w oder schreiben ist.