du da dos resultados diferentes para el mismo archivo


23

Soy un estudiante graduado de química computacional con acceso a un clúster de Linux. El clúster consta de un servidor de archivos muy grande (25 TB), al que están conectadas varias docenas de nodos de cómputo. Cada nodo de cómputo consta de 8 a 24 núcleos Intel Xeon. Cada nodo de proceso también contiene un disco local de aproximadamente 365 TB.

Dado que el servidor de archivos es accedido rutinariamente por una docena de usuarios en el grupo de investigación, el servidor de archivos se utiliza principalmente para el almacenamiento de archivos a largo plazo (se realiza una copia de seguridad todas las noches, mientras que los discos locales de los nodos de cómputo nunca se respaldan). Por lo tanto, el administrador del sistema nos ha indicado que ejecutemos simulaciones en los discos locales, que tienen E / S más rápidas que el servidor de archivos, para no ralentizar el servidor de archivos para los demás usuarios.

Entonces, ejecuto simulaciones en los discos locales y luego, una vez que terminan, copio los archivos de trayectoria (estoy ejecutando simulaciones de dinámica molecular (MD)) en el servidor de archivos para su almacenamiento. Supongamos que tengo un archivo llamado trayectoria traj.trren un directorio en el disco local de un nodo, /home/myusername/mysimulation1/traj.trr. Para el almacenamiento a largo plazo, siempre copio traj.trra un directorio en el servidor de archivos, ~/mysimulation1/traj.trrdonde ~representa mi directorio en el servidor de archivos, /export/home/myusername. Después de copiarlo, lo uso habitualmente du -hpara verificar que /home/myusername/mysimulation1/traj.trrtenga el mismo tamaño de archivo que ~/mysimulation1/traj.trr. De esta manera, puedo estar al menos razonablemente seguro de que la transferencia al servidor de archivos fue exitosa. Por ejemplo:

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

Si las dos llamadas du -hdan el mismo tamaño de archivo legible por humanos, entonces puedo estar razonablemente seguro de que la transferencia / copia fue exitosa. (Mis traj.trrarchivos típicos varían en tamaño de aproximadamente 15 a 20 GB, dependiendo de la simulación exacta que he ejecutado). Si ejecuto du(es decir, sin el -hinterruptor) en los dos traj.trrarchivos, sus tamaños en bytes son generalmente muy, muy similares. - generalmente dentro de unos pocos bytes. He estado usando este método general durante el último año y medio, sin problemas.

Sin embargo, recientemente me he encontrado con el siguiente problema: a vecesdu -hinforma quetraj.trrvarios archivos tienen un tamaño diferente en varios GB. Aquí hay un ejemplo:

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

El resultado de las dos llamadas a du -hes el siguiente, respectivamente:

20G     traj.trr
28G     traj.trr

Creo que el primero (es decir, traj.trren el disco local /home/myusername/mysimulation1/) es el tamaño de archivo correcto, ya que se espera que mis trayectorias de simulación sean de aproximadamente 15 a 20 GB cada una. Pero entonces, ¿cómo podría el archivo en el servidor de archivos en realidad ser más grande ? Pude ver cómo podría ser más pequeño, si de alguna manera la cptransferencia fallara. Pero no veo cómo podría ser más grande .

Obtengo resultados similares cuando ejecuto los mismos comandos que arriba, pero sin el -hinterruptor dado a du:

20717480        traj.trr
28666688        traj.trr

¿Se te ocurre alguna razón para la diferencia?

Si, por alguna improbable oportunidad, de dualguna manera funciona mal, puedo estar de acuerdo con eso. Pero realmente necesito asegurarme de que la copia del traj.trrservidor de archivos esté completa e sea idéntica a su versión de origen en el disco local. Necesito eliminar el archivo local para tener suficiente espacio en el disco local para ejecutar nuevas simulaciones, pero no puedo permitir que la versión del traj.trrservidor de archivos esté dañada.

El formato de archivo .trr (del paquete de dinámica molecular Gromacs) es un formato binario, no texto. Por lo tanto, no estoy seguro si los archivos pueden ser comparados de manera confiable por un programa como diff.


55
Intenta ejecutar md5sumo sha1sumen los archivos. ¿Se complementan?
cjm

2
@cjm Acabo de ejecutar md5sumen los dos archivos. Las dos sumas de verificación coinciden. Entonces, ¿supongo que esto significa que los dos archivos son iguales?
Andrew

3
¿De qué tamaños son reportados ls -l? El comando duinforma cuánto espacio en el disco se utiliza para su archivo, no qué tan grande es su archivo. El tamaño del disco puede verse influenciado por su sistema de archivos y sus estrategias de asignación.
casey

2
@casey ls -l -hdice que ambos archivos son de 20 GB. Del mismo modo, ls -ldice que ambos archivos son 21214683940 bytes. Así que supongo que los archivos son del mismo tamaño, pero no usan la misma cantidad de espacio en disco (según du).
Andrew

2
@ Andrew dado que los tamaños informados por ls son los mismos y los hash son los mismos, puede concluir que los archivos son los mismos. Estas herramientas son las que le dan la confianza que necesita y le muestran que du no es la herramienta para satisfacer sus necesidades.
casey

Respuestas:


32

Realmente deberías usar algo como md5sumo sha1sumpara verificar la integridad.

Si realmente quieres usar el tamaño, usa ls -lo du -b.

La duutilidad normalmente solo muestra el uso del disco en el archivo, es decir, qué cantidad del sistema de archivos utiliza. Este valor depende totalmente del sistema de archivos de respaldo y otros factores como los archivos dispersos.

Ejemplo:

$ 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

Tenemos dos archivos que contienen 512 MB de ceros. El primero se almacena escaso y no utiliza ningún espacio en disco, mientras que el segundo almacena cada byte explícitamente en el disco. - Mismo archivo, pero uso de disco completamente diferente.

La -bopción puede ser buena para ti:

   -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

Este es un problema común cuando coloca los mismos datos en 2 discos duros diferentes. Querrá ejecutar el ducomando con un conmutador adicional, suponiendo que lo tenga, que debería tener en cuenta que son nodos de Linux.

¿El interruptor?

   --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

Ejemplo

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

Los sistemas de archivos anteriores son un disco local ( /root) mientras que el otro /home/sames un recurso compartido NFS de mi 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

¿Entonces que hay de nuevo?

Esto confunde a mucha gente, pero recuerde que cuando los archivos se almacenan en un disco, consumen bloques de espacio, incluso si solo usan una parte de esos bloques. Cuando ejecuta dusin --apparent-sizeobtener el tamaño en función de la cantidad de espacio de bloque utilizado en el disco, no el espacio real consumido por los archivos.

usando una suma de verificación en su lugar?

Esta es probablemente una mejor opción si le preocupa comparar 2 árboles de archivos. Puede usar este comando para calcular una suma de verificación para todos los archivos y luego calcular una suma de verificación final de sumas de verificación. Este ejemplo usa, sha1sumpero podría usarlo con la misma facilidad md5sum.

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

Ejemplo

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

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

Entonces podemos ver que los 2 árboles son idénticos.

(Nota: el comando find enumerará los archivos tal como aparecieron en el sistema de archivos. Por lo tanto, si está comparando dos directorios del sistema de archivos diferente (por ejemplo, Ext3 vs. APFS), debe ordenar primero antes de la suma final sha1. Xianjun Dong)


5

La respuesta corta: no pruebe el tamaño del archivo, pruebe el estado de retorno del comando. El estado de retorno es la única indicación confiable de si la copia tuvo éxito (salvo comparar los dos archivos byte por byte, directamente o indirectamente, lo que es redundante si la copia tuvo éxito).

Verificar el tamaño del archivo no es una forma muy útil de verificar si una copia se realizó correctamente. En algunos casos, puede ser una comprobación de cordura útil, por ejemplo, cuando descarga un archivo de la web. Pero aquí hay una mejor manera.

Todos los comandos de Unix devuelven un estado para indicar si tuvieron éxito: 0 para el éxito, 1 o más para los errores. Así que verifique el estado de salida de cp. cpnormalmente habrá impreso un mensaje de error si falla, indicando cuál es el error. En un script, el estado de salida del último comando está en la variable mágica $?.

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

En lugar de verificar si $?es cero, puede usar operadores booleanos.

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

Si está ejecutando un script y desea que el script se detenga si falla algún comando, ejecute set -e. Si algún comando falla (es decir, devuelve un estado distinto de cero), el script saldrá inmediatamente con el mismo estado que el comando.

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

En cuanto a la razón por la cual el archivo copiado era más grande, debe ser porque era un archivo escaso . Los archivos dispersos son una forma cruda de compresión donde los bloques que contienen solo bytes nulos no se almacenan. Cuando copia un archivo, el cpcomando lee y escribe bytes nulos, por lo que cuando el original tenía bloques faltantes, la copia tiene bloques llenos de bytes nulos. En Linux, el cpcomando intenta detectar archivos dispersos, pero no siempre tiene éxito; cp --sparse=alwayshace que se esfuerce más a expensas de un ligero aumento en el tiempo de CPU.

De manera más general, dupodría arrojar resultados diferentes debido a otras formas de compresión. Sin embargo, los sistemas de archivos comprimidos son raros. Si desea saber el tamaño de un archivo como el número de bytes en el archivo, en lugar del número de bloques de disco que usa, use en ls -llugar de du.


¡Muchas gracias! ¿Sabes si hay una utilidad (separada) que me puede decir si mi archivo es escaso o no?
Andrew

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.