Depuis la lsof
page de manuel
Lsof renvoie un (1) si une erreur a été détectée, y compris l'échec de la localisation des noms de commande, des noms de fichiers, des adresses ou des fichiers Internet, des noms de connexion, des fichiers NFS, des PID, des PGID ou des UID qu'il a été invité à répertorier. Si l'option -V est spécifiée, lsof indiquera les éléments de recherche qu'il n'a pas réussi à répertorier.
Cela suggère donc que votre lsof failed for some other reason
clause ne sera jamais exécutée.
Avez-vous essayé de simplement déplacer le fichier alors que votre processus externe l'a toujours ouvert? Si le répertoire de destination se trouve sur le même système de fichiers, cela ne devrait poser aucun problème, sauf si vous devez y accéder sous le chemin d'origine à partir d'un troisième processus, car l'inode sous-jacent restera le même. Sinon, je pense mv
qu'il échouera de toute façon.
Si vous devez vraiment attendre que votre processus externe soit terminé avec le fichier, il est préférable d'utiliser une commande qui bloque au lieu de l'interrogation répétée. Sous Linux, vous pouvez l'utiliser inotifywait
pour cela. Par exemple:
inotifywait -e close_write /path/to/file
Si vous devez utiliser lsof
(peut-être pour la portabilité), vous pouvez essayer quelque chose comme:
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
Mettre à jour
Comme indiqué par @JohnWHSmith ci-dessous, la conception la plus sûre utiliserait toujours une lsof
boucle comme ci-dessus car il est possible que plus d'un processus ait le fichier ouvert pour l'écriture (un exemple de cas peut être un démon d'indexation mal écrit qui ouvre les fichiers avec la lecture / write flag alors qu'il devrait vraiment être en lecture seule). inotifywait
peut toujours être utilisé à la place du sommeil, remplacez simplement la ligne de sommeil par inotifywait -e close /path/to/file
.