Von der lsof
Manpage
Lsof gibt eine Eins (1) zurück, wenn ein Fehler festgestellt wurde, einschließlich des Fehlens des Auffindens von Befehlsnamen, Dateinamen, Internetadressen oder -dateien, Anmeldenamen, NFS-Dateien, PIDs, PGIDs oder UIDs, die aufgelistet werden sollen. Wenn die Option -V angegeben ist, gibt lsof die Suchelemente an, die nicht aufgelistet werden konnten.
Das 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:
inotifywait -e close_write /path/to/file
Wenn Sie verwenden müssen lsof
(möglicherweise aus Gründen der Portabilität), können Sie Folgendes ausprobieren:
until err_str=$(lsof /path/to/file 2>&1 >/dev/null); do
if [ -n "$err_str" ]; then
# lsof printed an error string, file may or may not be open
echo "lsof: $err_str" >&2
# tricky to decide what to do here, you may want to retry a number of times,
# but for this example just break
break
fi
# lsof returned 1 but didn't print an error string, assume the file is open
sleep 1
done
if [ -z "$err_str" ]; then
# file has been closed, move it
mv /path/to/file /destination/path
fi
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 durch inotifywait -e close /path/to/file
.