Ich möchte große Dateien, die von einem externen Prozess erstellt wurden, verschieben, sobald sie geschlossen sind.
Ist dieser Testbefehl korrekt?
if lsof "/file/name"
then
# file is open, don't touch it!
else
if [ 1 -eq $? ]
then
# file is closed
mv /file/name /other/file/name
else
# lsof failed for some other reason
fi
fi
BEARBEITEN: Die Datei stellt einen Datensatz dar und ich muss warten, bis er vollständig ist, um ihn zu verschieben, damit ein anderes Programm darauf reagieren kann. Deshalb muss ich wissen, ob der externe Prozess mit der Datei abgeschlossen ist.
linux
shell-script
monitoring
open-files
lsof
Peter Kovac
quelle
quelle
lsof
überhaupt nicht Ich muss nur überprüfen, ob die Dateierweiterung nicht ist.tmp
. Das macht es trivial. Ich bin jedoch froh, dass ich meine Frage gestellt habe, da ich etwas überlsof
undinotify
und so gelernt habe .Antworten:
Von der
lsof
ManpageDas würde also bedeuten, dass Ihre
lsof failed for some other reason
Klausel niemals ausgeführt wird.Haben Sie versucht, die Datei nur zu verschieben, während Ihr externer Prozess sie noch geöffnet hat? Wenn sich das Zielverzeichnis im selben Dateisystem befindet, sollte dies keine Probleme verursachen, es sei denn, Sie müssen von einem dritten Prozess aus unter dem ursprünglichen Pfad darauf zugreifen, da der zugrunde liegende Inode unverändert bleibt. Sonst denke ich
mv
wird sowieso scheitern.Wenn Sie wirklich warten müssen, bis Ihr externer Prozess mit der Datei abgeschlossen ist, sollten Sie einen Befehl verwenden, der blockiert, anstatt wiederholt abzufragen. Unter Linux können Sie
inotifywait
dies verwenden. Z.B:Wenn Sie verwenden müssen
lsof
(möglicherweise aus Gründen der Portabilität), können Sie Folgendes ausprobieren:Aktualisieren
Wie von @JohnWHSmith unten erwähnt, würde das sicherste Design immer eine
lsof
Schleife wie oben verwenden, da es möglich ist, dass mehr als ein Prozess die Datei zum Schreiben geöffnet hat (ein Beispielfall kann ein schlecht geschriebener Indexierungsdämon sein, der Dateien mit dem Lesevorgang öffnet / schreibe Flag, wenn es wirklich schreibgeschützt sein sollte).inotifywait
kann aber immer noch anstelle von Schlaf verwendet werden, ersetzen Sie einfach die Schlaflinie durchinotifywait -e close /path/to/file
.quelle
inotify
. Leider ist es nicht auf meiner Box installiert, aber ich bin sicher, dass ich irgendwo ein Paket finden werde. In meiner Bearbeitung finden Sie einen Grund, warum die Datei geschlossen werden muss: Es handelt sich um einen Datensatz, der vollständig sein muss, bevor er weiter verarbeitet werden kann.inotifywait
das Skript verhindert, dass das Skript häufig zwei "abfragt", muss das OP dennochlsof
eine Schleife einchecken : Wenn die Datei zweimal geöffnet wird, kann das einmalige Schließen dasinotify
Ereignis auslösen , obwohl die Datei noch nicht bereit ist manipuliert (zum Beispielsleep
könnte Ihr Anruf in Ihrem letzten Codeausschnitt durch ersetzt werdeninotifywait
).close_write
sollte in Ordnung sein, da nur ein Prozess die Datei gleichzeitig zum Schreiben öffnen kann. Es wird davon ausgegangen, dass ein anderer Benutzer es nicht direkt nach dem Schließen öffnet, aber dann besteht das gleiche Problem beimlsof
Abrufen.CLOSE_WRITE
wird sie zweimal ausgelöst).Als alternativer Ansatz ist dies der perfekte Fall für ein Rohr. Der zweite Prozess verarbeitet die Ausgabe des ersten Prozesses, sobald sie verfügbar ist, anstatt auf den Abschluss des vollständigen Prozesses zu warten:
Vorteile:
Wenn Sie keine Möglichkeit haben, eine Pipe direkt zu erstellen, aber GNU-Coreutils haben , können Sie Folgendes verwenden:
Dadurch wird die Eingabedatei von Anfang an gelesen, unabhängig davon, wie weit der erste Vorgang durch das Schreiben der Datei fortgeschritten ist (auch wenn sie noch nicht gestartet oder bereits abgeschlossen ist).
quelle
cat
undprocess2
könnte beenden, bevorprocess1
fertig ist. Sie würden nicht blockieren.