GNU/Linux >> Tutoriels Linux >  >> Linux

Déplacer le fichier mais seulement s'il est fermé

A partir du 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 commandes, des noms de fichiers, des adresses Internet ou des fichiers, des noms de connexion, des fichiers NFS, des PID, des PGID ou des UID qu'il a été demandé de lister. Si l'option -V est spécifiée, lsof indiquera les éléments de recherche qu'il n'a pas réussi à lister.

Cela suggérerait donc que votre lsof failed for some other reason clause ne serait jamais exécutée.

Avez-vous simplement essayé de 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 échouera de toute façon.

Si vous avez vraiment besoin d'attendre que votre processus externe ait terminé avec le fichier, il est préférable d'utiliser une commande qui bloque au lieu d'interroger à plusieurs reprises. Sous Linux, vous pouvez utiliser inotifywait pour ça. Ex :

 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 noté par @JohnWHSmith ci-dessous, la conception la plus sûre utiliserait toujours un lsof boucle comme ci-dessus car il est possible que plus d'un processus ait le fichier ouvert en écriture (un exemple de cas peut être un démon d'indexation mal écrit qui ouvre des fichiers avec l'indicateur de lecture/écriture alors qu'il devrait vraiment être en lecture seule). inotifywait peut toujours être utilisé à la place de sleep, il suffit de remplacer la ligne sleep par inotifywait -e close /path/to/file .


Comme approche alternative, c'est le cas parfait pour un tuyau - le deuxième processus traitera la sortie du premier processus dès qu'elle sera disponible, plutôt que d'attendre la fin du processus complet :

process1 input_file.dat | process2 > output_file.dat

Avantages :

  • Beaucoup plus rapide en général :
    • N'a pas besoin d'écrire et de lire sur le disque (ceci peut être évité si vous utilisez un disque virtuel).
    • Devrait utiliser plus complètement les ressources de la machine.
  • Aucun fichier intermédiaire à supprimer après avoir terminé.
  • Aucun verrouillage complexe nécessaire, comme dans OP.

Si vous n'avez aucun moyen de créer directement un tube mais que vous avez GNU coreutils vous pouvez utiliser ceci :

tail -F -n +0 input_file.dat | process2 > output_file.dat

Cela commencera à lire le fichier d'entrée depuis le début, peu importe la distance le premier processus consiste à écrire le fichier (même s'il n'est pas encore commencé ou déjà terminé).


Linux
  1. Déplacer des fichiers dans le terminal Linux

  2. Linux - Autorisation de fichier Exécuter uniquement ?

  3. Facl Ignorant La Permission "x" Mais Uniquement Sur Les Fichiers ?

  4. Comment créer un fichier uniquement s'il n'existe pas ?

  5. déplacer uniquement si le fichier existe dans un script shell

Comment déplacer un fichier sous Linux

Comment rediriger uniquement Stderr ?

Diff -r uniquement pour certains types de fichiers ?

Afficher uniquement Stderr à l'écran, mais écrire à la fois Stdout et Stderr dans un fichier ?

Comment utiliser la commande lsof sous Linux

La commande de déplacement de fichier Linux - simplifiée !