GNU/Linux >> Linux Esercitazione >  >> Linux

Sposta il file ma solo se è chiuso

Dal lsof pagina man

Lsof restituisce uno (1) se è stato rilevato un errore, incluso l'errore di individuare nomi di comandi, nomi di file, indirizzi o file Internet, nomi di accesso, file NFS, PID, PGID o UID che è stato richiesto di elencare. Se viene specificata l'opzione -V, lsof indicherà gli elementi di ricerca che non è riuscito a elencare.

Quindi questo suggerirebbe che il tuo lsof failed for some other reason la clausola non verrebbe mai eseguita.

Hai provato a spostare il file mentre il tuo processo esterno lo ha ancora aperto? Se la directory di destinazione si trova sullo stesso filesystem, non dovrebbero esserci problemi a farlo a meno che non sia necessario accedervi nel percorso originale da un terzo processo poiché l'inode sottostante rimarrà lo stesso. Altrimenti penso mv fallirà comunque.

Se hai davvero bisogno di aspettare fino a quando il tuo processo esterno non ha finito con il file, è meglio usare un comando che blocchi invece di eseguire ripetutamente il polling. Su Linux, puoi usare inotifywait per questo. Ad esempio:

 inotifywait -e close_write /path/to/file

Se devi usare lsof (forse per la portabilità), potresti provare qualcosa del tipo:

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

Aggiorna

Come notato da @JohnWHSmith di seguito, il design più sicuro userebbe sempre un lsof loop come sopra poiché è possibile che più di un processo abbia il file aperto per la scrittura (un caso di esempio potrebbe essere un demone di indicizzazione scritto male che apre i file con il flag di lettura/scrittura quando in realtà dovrebbe essere di sola lettura). inotifywait può comunque essere utilizzato al posto di sleep, basta sostituire la riga sleep con inotifywait -e close /path/to/file .


Come approccio alternativo, questo è il caso perfetto per una pipa - il secondo processo elaborerà l'output del primo processo non appena sarà disponibile, anziché attendere il completamento dell'intero processo:

process1 input_file.dat | process2 > output_file.dat

Vantaggi:

  • Molto più veloce in generale:
    • Non deve scrivere e leggere dal disco (questo può essere evitato se usi un ramdisk).
    • Dovrebbe utilizzare le risorse della macchina in modo più completo.
  • Nessun file intermedio da rimuovere al termine.
  • Non è necessario alcun blocco complesso, come in OP.

Se non hai modo di creare direttamente una pipe ma hai GNU coreutils puoi usare questo:

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

Questo inizierà a leggere il file di input dall'inizio, non importa quanto lontano il primo processo consiste nella scrittura del file (anche se non è ancora iniziato o è già terminato).


Linux
  1. Come determinare quale processo sta creando un file?

  2. Linux – Solo per l'esecuzione di autorizzazioni file?

  3. Facl ignorando l'autorizzazione "x" ma solo sui file?

  4. lsof :esempi più comunemente usati

  5. Comandi di base vi (cheat sheet)

Come spostare un file in Linux

Diff -r Solo per determinati tipi di file?

Mostra solo Stderr sullo schermo ma scrivi sia Stdout che Stderr su file?

Come usare il comando lsof in Linux

Il comando di spostamento del file di Linux:semplificato!

Come creare un file solo se non esiste?