du fornisce due risultati diversi per lo stesso file


23

Sono uno studente laureato di chimica computazionale con accesso a un cluster Linux. Il cluster è costituito da un file server molto grande (25 TB), al quale sono collegate diverse decine di nodi di calcolo. Ogni nodo di calcolo è composto da 8 a 24 core Intel Xeon. Ogni nodo di calcolo contiene anche un disco locale di circa 365 TB.

Dato che al dozzina accedono regolarmente al file server una dozzina di utenti nel gruppo di ricerca, il file server viene utilizzato principalmente per l'archiviazione di file a lungo termine (viene eseguito il backup di notte, mentre i dischi locali dei nodi di calcolo non vengono mai sottoposti a backup). Pertanto, l'amministratore di sistema ci ha incaricato di eseguire simulazioni sui dischi locali - che hanno un I / O più veloce rispetto al file server - in modo da non rallentare il file server per gli altri utenti.

Quindi, eseguo simulazioni sui dischi locali e poi, una volta terminato, copio i file di traiettoria - sto eseguendo simulazioni di dinamica molecolare (MD) - sul file server per l'archiviazione. Supponiamo che io sono un file chiamato traiettoria traj.trrin una directory sul disco locale di un nodo, /home/myusername/mysimulation1/traj.trr. Per la conservazione a lungo termine, ho sempre copiare traj.trrin una directory nel fileserver, ~/mysimulation1/traj.trrdove ~rappresenta il mio directory nel fileserver, /export/home/myusername. Dopo averlo copiato, lo uso abitualmente du -hper verificare che /home/myusername/mysimulation1/traj.trrabbia le stesse dimensioni del file ~/mysimulation1/traj.trr. In questo modo, posso essere almeno ragionevolmente sicuro che il trasferimento al fileserver sia andato a buon fine. Per esempio:

cd /home/myusername/mysimulation1/
cp -v traj.trr ~/mysimulation1/
du /home/myusername/mysimulation1/traj.trr -h
du ~/mysimulation1/traj.trr -h

Se le due chiamate du -hdanno la stessa dimensione di file leggibile dall'uomo, allora posso essere ragionevolmente sicuro che il trasferimento / copia sia andato a buon fine. (I miei traj.trrfile tipici hanno una dimensione compresa tra circa 15 e 20 GB, a seconda della simulazione esatta che ho eseguito.) Se corro du(cioè senza l' -hinterruttore) sui due traj.trrfile, le loro dimensioni in byte sono di solito molto, molto simili - - di solito entro pochi byte. Ho usato questo metodo generale nell'ultimo anno e mezzo, senza problemi.

Tuttavia, recentemente ho riscontrato il seguente problema: a voltedu -hsegnala che i duetraj.trrfile hanno dimensioni diverse di diversi GB. Ecco un esempio:

cd /home/myusername/mysimulation1/            # this is the local disk
cp -v traj.trr ~/mysimulation1/
du traj.trr -h
cd ~/mysimulation1/                           # this is the fileserver
du traj.trr -h

L'output delle due chiamate a du -hè rispettivamente il seguente:

20G     traj.trr
28G     traj.trr

Credo che il primo (ovvero, traj.trrnel disco locale /home/myusername/mysimulation1/) abbia le dimensioni corrette del file, poiché le mie traiettorie di simulazione dovrebbero essere di circa 15-20 GB ciascuna. Ma allora come potrebbe il file sul file server essere effettivamente più grande ? Ho potuto vedere come potrebbe essere più piccolo, se in qualche modo il cptrasferimento non è riuscito. Ma non vedo come potrebbe effettivamente essere più grande .

Ottengo un output simile quando eseguo gli stessi comandi di cui sopra, ma senza lo -hswitch dato a du:

20717480        traj.trr
28666688        traj.trr

Riesci a pensare a qualche motivo per la differenza?

Se, per qualche improbabile possibilità, dufunziona in qualche modo, posso essere d'accordo. Ma ho davvero bisogno di assicurarmi che la copia di traj.trrsul file server sia completa e identica alla sua versione di origine sul disco locale. Devo eliminare il file locale in modo da disporre di spazio su disco locale sufficiente per eseguire nuove simulazioni, ma non posso permettermi di avere la versione di traj.trrsul file server danneggiata.

Il formato di file .trr (dal pacchetto di dinamica molecolare Gromacs) è un formato binario, non testo. Pertanto, non sono sicuro che i file possano essere confrontati in modo affidabile da un programma come diff.


5
Prova a eseguire md5sumo sha1sumsui file. Si abbinano?
cjm

2
@cjm Ho appena eseguito md5sumi due file. I due checksum corrispondono. Quindi suppongo che questo significhi che i due file sono uguali?
Andrew,

3
Di quali dimensioni sono riportate ls -l? Il comando duindica la quantità di spazio sul disco utilizzata per il file, non la dimensione del file. Le dimensioni sul disco possono essere influenzate dal tuo filesystem e dalle sue strategie di allocazione.
Casey,

2
@casey ls -l -hafferma che entrambi i file sono 20 GB. Allo stesso modo, ls -ldice che entrambi i file sono 21214683940 byte. Quindi immagino che i file abbiano le stesse dimensioni, ma non utilizzino la stessa quantità di spazio su disco (secondo du).
Andrew, il

2
@Andrew dato che le dimensioni riportate da ls sono le stesse e gli hash sono gli stessi puoi concludere che i file sono gli stessi. Questi strumenti sono ciò che ti dà la sicurezza di cui hai bisogno e ti mostrano che du non è lo strumento per soddisfare le tue esigenze.
Casey,

Risposte:


32

Dovresti davvero usare qualcosa di simile md5sumo sha1sumper verificare l'integrità.

Se vuoi davvero usare le dimensioni usa ls -lo du -b.

L' duutilità normalmente mostra solo l'utilizzo del disco del file, ovvero la quantità di file system utilizzata da esso. Questo valore dipende totalmente dal file system di supporto e da altri fattori come i file sparsi.

Esempio:

$ truncate -s 512M foo
$ cat foo >bar
$ ls -l foo bar
-rw-r--r-- 1 michas users 536870912 23. Dez 00:06 bar
-rw-r--r-- 1 michas users 536870912 23. Dez 00:03 foo
$ du foo bar
0       foo
524288  bar
$ du -b foo bar
536870912       foo
536870912       bar

Abbiamo due file contenenti entrambi 512 MB di zeri. Il primo è archiviato in modo sparso e non utilizza spazio su disco, mentre il secondo memorizza esplicitamente ogni byte sul disco. - Stesso file, ma utilizzo del disco completamente diverso.

L' -bopzione potrebbe essere buona per te:

   -b, --bytes
          equivalent to '--apparent-size --block-size=1'

   --apparent-size
          print apparent sizes, rather than disk usage; although the apparent
          size is  usually  smaller,  it  may  be  larger  due  to  holes  in
          ('sparse')  files, internal fragmentation, indirect blocks, and the
          like

8

Questo è un problema comune quando si inseriscono gli stessi dati su 2 diversi HDD. Ti consigliamo di eseguire il ducomando con un interruttore aggiuntivo, supponendo che ce l'abbia - che dovrebbe dare questi sono nodi Linux.

L'interruttore?

   --apparent-size
          print  apparent  sizes,  rather  than  disk  usage;  although the 
          apparent size is usually smaller, it may be larger due to holes in
          ('sparse') files, internal fragmentation, indirect blocks, and the 
          like

Esempio

$ du -sh --apparent-size /home/sam/scsconfig.log ~/scsconfig.log 
93K /home/sam/scsconfig.log
93K /root/scsconfig.log

I filesystem sopra sono un disco locale ( /root) mentre l'altro /home/samè una condivisione NFS dal mio NAS.

$ df -h . /home/sam
Filesystem            Size  Used Avail Use% Mounted on
/dev/mapper/VolGroup00-LogVol00
                      222G  118G   92G  57% /
mulder:/export/raid1/home/sam
                      917G  566G  305G  65% /home/sam

Allora, come va?

Questo confonde molte persone, ma ricorda che quando i file sono memorizzati su un disco consumano blocchi di spazio anche se usano solo una parte di quei blocchi. Quando si esegue dusenza il, --apparent-sizesi ottengono le dimensioni in base alla quantità di spazio di blocco del disco utilizzata, non allo spazio effettivo consumato dai file.

usando invece un checksum?

Questa è probabilmente un'opzione migliore se sei preoccupato di confrontare 2 alberi di file. È possibile utilizzare questo comando per calcolare un checksum per tutti i file e quindi calcolare un checksum finale dei checksum. Questo esempio usa sha1summa potresti usare altrettanto facilmente md5sum.

$ cd /some/dir
$ find . -type f \( -exec sha1sum "{}" \; \) | sort -k2,2 | sha1sum

Esempio

$ cd ~/dir1
$ find . -type f \( -exec sha1sum "{}" \; \) | sort -k2,2 | sha1sum
55e2672f8d6fccff6d83f0bffba1b67aeab87911  -

$ cd ~/dir2
$ find . -type f \( -exec sha1sum "{}" \; \) | sort -k2,2 | sha1sum
55e2672f8d6fccff6d83f0bffba1b67aeab87911  -

Quindi possiamo vedere che i 2 alberi sono identici.

(Nota: il comando find elenca i file così come apparivano nel file system. Quindi, se si stanno confrontando due directory dal diverso file system (es. Ext3 vs. APFS), è necessario ordinare prima del sha1sum finale. (Aggiunto da Xianjun Dong)


5

La risposta breve: non testare la dimensione del file, testare lo stato di ritorno del comando. Lo stato di restituzione è solo un'indicazione affidabile del successo della copia (a parte il confronto dei due file byte per byte, direttamente o indirettamente - che è ridondante se la copia ha avuto successo).

Controllare le dimensioni del file non è un modo molto utile per verificare se una copia è riuscita. In alcuni casi, può essere un utile controllo di integrità, ad esempio quando si scarica un file dal Web. Ma qui c'è un modo migliore.

Tutti i comandi Unix restituiscono uno stato per indicare se sono riusciti: 0 per successo, 1 o più per errori. Quindi controlla lo stato di uscita di cp. cpnormalmente avrà stampato un messaggio di errore se fallito, indicando qual è l'errore. In uno script, lo stato di uscita dell'ultimo comando è nella variabile magica $?.

cp -v traj.trr ~/mysimulation1/
if [ $? -ne 0 ]; then
  echo 1>&2 "cp failed due to the error above"
  exit 2
 fi

Invece di verificare se $?è zero, è possibile utilizzare operatori booleani.

cp -v traj.trr ~/mysimulation1/ || exit 2

Se stai eseguendo uno script e vuoi che lo script si fermi se un comando non riesce, esegui set -e. Se un comando non riesce (ovvero restituisce uno stato diverso da zero), lo script uscirà immediatamente con lo stesso stato del comando.

set -e
…
cp -v traj.trr ~/mysimulation1/

Per quanto riguarda il motivo per cui il tuo file copiato era più grande, deve essere dovuto al fatto che era un file sparso . I file sparsi sono una forma grezza di compressione in cui non vengono memorizzati blocchi contenenti solo byte null. Quando si copia un file, il cpcomando legge e scrive byte null, quindi laddove l'originale avesse blocchi mancanti, la copia ha blocchi pieni di byte null. Sotto Linux, il cpcomando tenta di rilevare file sparsi, ma non sempre ha esito positivo; cp --sparse=alwayslo rende più difficile a scapito di un leggero aumento del tempo della CPU.

Più in generale, dupotrebbero restituire risultati diversi a causa di altre forme di compressione. Tuttavia, i filesystem compressi sono rari. Se vuoi conoscere la dimensione di un file come nel numero di byte nel file, al contrario del numero di blocchi del disco che usa, usa ls -linvece di du.


Grazie mille! Sai se esiste un'utilità (separata) che può dirmi se il mio file è scarso?
Andrew,

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.