du donne deux résultats différents pour le même fichier

23

Je suis un étudiant diplômé en chimie computationnelle avec accès à un cluster Linux. Le cluster est constitué d'un très grand serveur de fichiers (25 To), auquel plusieurs dizaines de nœuds de calcul sont connectés. Chaque nœud de calcul se compose de 8 à 24 cœurs Intel Xeon. Chaque nœud de calcul contient également un disque local d'environ 365 To.

Étant donné que le serveur de fichiers est régulièrement consulté par une douzaine d'utilisateurs du groupe de recherche, le serveur de fichiers est principalement utilisé pour le stockage de fichiers à long terme (il est sauvegardé tous les soirs, tandis que les disques locaux des nœuds de calcul ne sont jamais sauvegardés). Ainsi, l'administrateur système nous a demandé d'exécuter des simulations sur les disques locaux - qui ont des E / S plus rapides que le serveur de fichiers - afin de ne pas ralentir le serveur de fichiers pour les autres utilisateurs.

Donc, j'exécute des simulations sur les disques locaux, puis, une fois qu'elles sont terminées, je copie les fichiers de trajectoire - j'exécute des simulations de dynamique moléculaire (MD) - sur le serveur de fichiers pour les stocker. Supposons que j'ai un fichier de trajectoire appelé traj.trrdans un répertoire sur le disque local d'un nœud, /home/myusername/mysimulation1/traj.trr. Pour le stockage à long terme, je copie toujours traj.trrà un répertoire dans le serveur de fichiers, ~/mysimulation1/traj.trr~représente mon répertoire dans le serveur de fichiers, /export/home/myusername. Après l'avoir copié, je l'utilise habituellement du -hpour vérifier qu'il /home/myusername/mysimulation1/traj.trra la même taille de fichier que ~/mysimulation1/traj.trr. De cette façon, je peux être au moins raisonnablement sûr que le transfert vers le serveur de fichiers a réussi. Par exemple:

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

Si les deux appels du -hdonnent la même taille de fichier lisible par l'homme, je peux être raisonnablement sûr que le transfert / la copie a réussi. (La traj.trrtaille de mes fichiers typiques varie d'environ 15 à 20 Go, selon la simulation exacte que j'ai exécutée.) Si je lance du(c'est-à-dire sans le -hcommutateur) sur les deux traj.trrfichiers, leurs tailles en octets sont généralement très, très similaires - - généralement en quelques octets seulement. J'utilise cette méthode globale depuis un an et demi, sans aucun problème.

Cependant, récemment, j'ai rencontré le problème suivant:du -hsignaleparfoisque les deuxtraj.trrfichiers sont de taille différente de plusieurs Go. Voici un exemple:

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

La sortie des deux appels à du -hest la suivante, respectivement:

20G     traj.trr
28G     traj.trr

Je crois que le premier (c'est-à-dire le traj.trrsur le disque local /home/myusername/mysimulation1/) est de la bonne taille de fichier, car mes trajectoires de simulation devraient être d'environ 15 à 20 Go chacune. Mais alors, comment le fichier sur le serveur de fichiers pourrait-il être plus volumineux ? Je pouvais voir comment il pourrait être plus petit, si le cptransfert échouait. Mais je ne vois pas comment cela pourrait être plus important .

J'obtiens une sortie similaire lorsque j'exécute les mêmes commandes que ci-dessus, mais sans le -hcommutateur donné à du:

20717480        traj.trr
28666688        traj.trr

Pouvez-vous penser à une raison de la différence?

Si, par une chance improbable, duest en quelque sorte dysfonctionnement, je peux être d'accord avec cela. Mais je dois vraiment m'assurer que la copie de traj.trrsur le serveur de fichiers est complète et identique à sa version source sur le disque local. J'ai besoin de supprimer le fichier local afin d'avoir suffisamment d'espace disque local pour exécuter de nouvelles simulations, mais je ne peux pas me permettre de traj.trrcorrompre la version de sur le serveur de fichiers.

Le format de fichier .trr (du package de dynamique moléculaire Gromacs) est un format binaire, pas de texte. Ainsi, je ne sais pas si les fichiers peuvent être comparés de manière fiable par un programme tel que diff.

Andrew
la source
5
Essayez d'exécuter md5sumou sha1sumsur les fichiers. Correspondent-ils?
cjm
2
@cjm Je viens de courir md5sumsur les deux fichiers. Les deux sommes de contrôle correspondent. Donc je suppose que cela signifie que les deux fichiers sont identiques?
Andrew
3
Quelles tailles sont signalées par ls -l? La commande duindique la quantité d'espace sur le disque utilisée pour votre fichier, et non sa taille. La taille du disque peut être influencée par votre système de fichiers et ses stratégies d'allocation.
casey
2
@casey ls -l -hindique que les deux fichiers font 20 Go. De même, ls -ldit que les deux fichiers font 21214683940 octets. Je suppose donc que les fichiers sont de la même taille, mais n'utilisent pas la même quantité d'espace disque (selon du).
Andrew
2
@Andrew étant donné que les tailles rapportées par ls sont les mêmes et que les hachages sont les mêmes, vous pouvez conclure que les fichiers sont les mêmes. Ces outils vous donnent la confiance dont vous avez besoin et vous montrent que du n'est pas l'outil pour répondre à vos besoins.
casey

Réponses:

32

Vous devriez vraiment utiliser quelque chose comme md5sumou sha1sumpour vérifier l'intégrité.

Si vous voulez vraiment utiliser la taille, utilisez ls -lou du -b.

L' duutilitaire n'affiche normalement que l'utilisation du disque du fichier, c'est-à-dire la quantité de système de fichiers qu'il utilise. Cette valeur dépend totalement du système de fichiers de sauvegarde et d'autres facteurs tels que les fichiers épars.

Exemple:

$ 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

Nous avons deux fichiers contenant chacun 512 Mo de zéros. Le premier est stocké clairsemé et n'utilise aucun espace disque, tandis que le second stocke explicitement chaque octet sur le disque. - Même fichier, mais utilisation du disque complètement différente.

L' -boption pourrait vous convenir:

   -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
michas
la source
8

Il s'agit d'un problème courant lorsque vous mettez les mêmes données sur 2 disques durs différents. Vous voudrez exécuter la ducommande avec et un commutateur supplémentaire, en supposant qu'il l'ait - ce qu'il devrait donner, ce sont des nœuds Linux.

L'interrupteur?

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

Exemple

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

Les systèmes de fichiers ci-dessus sont un disque local ( /root) tandis que l'autre /home/samest un partage NFS de mon 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

Alors, quoi de neuf?

Cela déroute beaucoup de gens, mais rappelez-vous que lorsque les fichiers sont stockés sur un disque, ils consomment des blocs d'espace même s'ils n'utilisent qu'une partie de ces blocs. Lorsque vous exécutez dusans, --apparent-sizevous obtenez la taille en fonction de la quantité d'espace de bloc du disque utilisée, et non de l'espace réel consommé par le ou les fichiers.

utiliser une somme de contrôle à la place?

C'est probablement une meilleure option si vous souhaitez comparer 2 arbres de fichiers. Vous pouvez utiliser cette commande pour calculer une somme de contrôle pour tous les fichiers, puis calculer une somme de contrôle finale des sommes de contrôle. Cet exemple utilise sha1summais vous pouvez tout aussi bien l'utiliser à la md5sumplace.

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

Exemple

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

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

On voit donc que les 2 arbres sont identiques.

(Remarque: la commande find répertorie les fichiers tels qu'ils sont apparus dans le système de fichiers. Donc, si vous comparez deux répertoires du système de fichiers différent (par exemple, Ext3 vs APFS), vous devez trier d'abord avant le sha1sum final. (Ajouté par Xianjun Dong)

slm
la source
5

La réponse courte: ne testez pas la taille du fichier, testez le statut de retour de la commande. Le statut de retour n'est qu'une indication fiable de la réussite de la copie (à moins de comparer les deux fichiers octet par octet, directement ou indirectement - ce qui est redondant si la copie a réussi).

La vérification de la taille du fichier n'est pas un moyen très utile de vérifier si une copie a réussi. Dans certains cas, il peut s'agir d'une vérification d'esprit utile, par exemple lorsque vous téléchargez un fichier sur le Web. Mais ici, il y a une meilleure façon.

Toutes les commandes Unix renvoient un état pour indiquer si elles ont réussi: 0 pour réussir, 1 ou plus pour les erreurs. Vérifiez donc l'état de sortie de cp. cpaura normalement imprimé un message d'erreur en cas d'échec, indiquant ce qu'est l'erreur. Dans un script, l'état de sortie de la dernière commande se trouve dans la variable magique $?.

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

Au lieu de vérifier si $?est zéro, vous pouvez utiliser des opérateurs booléens.

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

Si vous exécutez un script et souhaitez que le script s'arrête si une commande échoue, exécutez set -e. Si une commande échoue (c.-à-d. Renvoie un état différent de zéro), le script se fermera immédiatement avec le même état que la commande.

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

Quant à la raison pour laquelle votre fichier copié était plus volumineux, ce doit être parce qu'il s'agissait d'un fichier clairsemé . Les fichiers épars sont une forme brute de compression où les blocs contenant uniquement des octets nuls ne sont pas stockés. Lorsque vous copiez un fichier, la cpcommande lit et écrit des octets nuls, donc là où l'original avait des blocs manquants, la copie a des blocs pleins d'octets nuls. Sous Linux, la cpcommande essaie de détecter des fichiers épars, mais elle ne réussit pas toujours; cp --sparse=alwaysle rend plus difficile au détriment d'une très légère augmentation du temps CPU.

Plus généralement, dupourrait renvoyer des résultats différents en raison d'autres formes de compression. Les systèmes de fichiers compressés sont cependant rares. Si vous voulez connaître la taille d'un fichier comme le nombre d'octets dans le fichier, par opposition au nombre de blocs de disque qu'il utilise, utilisez à la ls -lplace de du.

Gilles 'SO- arrête d'être méchant'
la source
Merci beaucoup! Savez-vous s'il existe un utilitaire (distinct) qui peut me dire si mon fichier est rare ou non?
Andrew
@Andrew Voir Trouver des fichiers épars? et informations détaillées sur les fichiers clairsemés sur Linux
Gilles «SO- arrête d'être mal»