Soluzione 1:
La soluzione migliore è usare lsof
per determinare se un file è stato aperto da qualsiasi processo:
# lsof -f -- /var/log/syslog
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
rsyslogd 1520 syslog 1w REG 252,2 72692 16719 /var/log/syslog
Non puoi dire facilmente se è in fase di scrittura, ma se è in fase di scrittura, DEVE essere aperto.
Modifica:risolviamo qui il vero problema piuttosto che provare a implementare la soluzione proposta!
Usa rsync per trasferire il file:
○ → rsync -e ssh remote:big.tar.gz .
In questo modo, il file non verrà copiato sopra quello esistente ma copiato in un file temporaneo (.big.tar.gz.XXXXXX
) fino al completamento del trasferimento, quindi spostato in posizione.
Soluzione 2:
Sei sulla buona strada, rinominare il file è un'operazione atomica, quindi eseguire la rinomina dopo il caricamento è semplice, elegante e non soggetto a errori. Un altro approccio che mi viene in mente è usare lsof | grep filename.tar.gz
per verificare se il file è in fase di accesso da parte di un altro processo.
Soluzione 3:
Un po' datato, ma la maggior parte delle risposte manca completamente il punto della domanda:
Ma ho pensato di provare a capire se c'è semplicemente un modo per determinare se il file è intero prima dalla riga di comando...
In generale non c'è. Semplicemente non hai abbastanza informazioni per determinarlo.
Perché determinare che il file è chiuso non equivale a determinare se il file è intero . Ad esempio, un file verrà "chiuso" se la connessione viene persa durante il trasferimento.
Solo la risposta di @ Alex ha capito bene. E anche lui si è innamorato dell'uso di lsof
un po'.
Per determinare se il file è stato completamente trasferito correttamente, sono necessari più dati. Ad esempio:
Un'alternativa a cui stavo pensando era di copiare il file con un'estensione di file diversa (come
.tar.gz.part
) e poi rinominato in.tar.gz
al termine del trasferimento.
Questo è un modo perfetto per comunicare che il file è stato trasferito completamente e con successo. Puoi anche spostare i file da una directory all'altra fintanto che rimani all'interno dello stesso filesystem. Oppure chiedi al mittente di inviare un filename.done
vuoto file per segnalare il completamento.
Ma tutti i metodi devono fare affidamento sul mittente che in qualche modo segnala che il trasferimento è stato completato con successo. Perché solo il mittente ha queste informazioni.
Alcuni formati di file (come i PDF) contengono dati che consentono di determinare se il file è completo. Ma devi aprire e leggere praticamente l'intero file per scoprirlo.
lsof
ti dirà solo che il file non è più aperto, non ti dirà perché non è più aperto. Né ti dirà quanto dovrebbe essere grande il file.
Soluzione 4:
Il modo migliore per farlo è usare incron ("inotify cron system"). Ti consente di impostare un controllo inotify su una directory che ti avviserà quindi delle operazioni sui file. In questo caso, dovresti guardare la directory per un close_write. Ciò ti consentirà di eseguire il tuo comando una volta che il file è stato chiuso dopo una scrittura.
Soluzione 5:
Sembra che lsof possa rilevare in quale modalità è aperto un file:
lsof -f -- a_file
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
cat 52391 bob 1w REG 1,2 15 19545007 a_file
Vedi dove dice 1w? Ciò significa che il numero del descrittore di file è 1 e la modalità è w, o write.