# [checksum] Vérifier des copies [solved]

## Jamesbch

Bonjour à tous,

J'ai fais de grosses copies en ce moment, afin de déplacer des données et de les sauver. Enfin bref, je cherche à vérifier si les données ont bien été copiées octets pour octets.

J'aurai besoin d'un outil qui vérifie dans une arborescence mirroir si les fichiers ont la méme valeur de vérification. Par exemple avec CRC32, ou MD5 ou SHA. Vu qu'il s'agit de 170GB de donnée environ il faudrait qu'il soit rapide, enfin je vais pas faire le difficile, je suis ouvert à tout.

Pour résumé: Comment vérifier l'exactitude de copies de fichiers? (Par exemple vérifier que tous les dossiers et fichiers de /mnt/disque1 et /mnt/disque2 sont strictement identiques)

Je vous remercie d'avance !Last edited by Jamesbch on Sat Jul 12, 2008 8:32 pm; edited 1 time in total

----------

## geekounet

T'as une option --checksum avec rsync, ça pourrait faire ton affaire  :Smile:  (en rajoutant les options qui vont bien pour ne faire aucun transferts si tu veux vraiment qu'une simple vérification)

----------

## Jamesbch

En effet rsync c'est peut-être une bonne idée. Je crois que j'ai trouvé une option -a qui fait en local. Ca m'affiche tous les dossiers avec -avr est-ce qu'il vérifie ? Je ne sais même pas ce qu'il fait. On verra quand il aura fini.Last edited by Jamesbch on Sat Jul 12, 2008 4:29 pm; edited 1 time in total

----------

## razer

 *Jamesbch wrote:*   

> Bonjour à tous,
> 
> ans une arborescence mirroir si les fichiers ont la méme valeur de vérification. Par exemple avec CRC32, ou MD5 ou SHA. Vu qu'il s'agit de 170GB de donnée environ il faudrait qu'il soit rapide, enfin je vais pas faire le difficile, je suis ouvert à tout.
> 
> 

 

Bonjour,

J'imagine que si tu veux faire du mirror, c'est que le contenu de ton arborescence évolue continuellement. Par conséquent, je ne vois pas comment tu pourrais mettre en place un système style MD5, car le chiffrage devra être réalisé à chaque changement dans un fichier.

En clair, le MD5 est intéressant pour vérifier plusieurs copies à partir d'une source, mais là comme il y a qu'une copie je ne vois pas ce qu'il pourrait t'apporter.

Il est aussi possible que j'ai rien compris au système de chiffrage, mais...

Pour résoudre ton problème, perso j'utiliserais un truc bien bourrin du style "diff -r". Cà sera long, mais je ne vois pas de recette plus rapide. Par ailleurs cela t'impose que personne ne modifie de fichier entre le début de ton mirroring et la fin de ton diff, ce qui peut être contraignant.

----------

## Magic Banana

sha1sum c'est bien.  :Smile: 

J'en profite pour reposter ici un script Shell que j'avais écris pour un autre utilisateur du forum (dont le disque destination semblait poser des problèmes). Il copie un fichier morceau par morceau en vérifiant à chaque fois que le morceau copié est intègre. Si il ne l'est pas, seul le morcau concerné est renvoyé :

```
#!/bin/bash

BLOCK=2000

CHECKSUM="sha1sum"

if [ -z "$2" ]

then

    echo "Usage: safe-cp src dest"

    exit 64

fi

rm "$2" 2> /dev/null

offset=0

isize=`wc -c "$1" | awk '{print $1}'`

osize=0

while [ $osize -ne $isize ]

do

    dd if="$1" of="$2" skip=$offset seek=$offset count=$BLOCK 2> /dev/null

    if [ `dd if="$1" skip=$offset count=$BLOCK 2> /dev/null | $CHECKSUM | awk '{print $1}'` = `dd if="$1" skip=$offset count=$BLOCK 2> /dev/null | $CHECKSUM | awk '{print $1}'` ]

    then

   osize=`wc -c "$2" | awk '{print $1}'`

   offset=`expr $offset + $BLOCK`   

    fi

done

exit 0
```

Si tu dois souvent copié ce autant d'information et que l'intégrité pose problème, cela te sera utile. Il faut toutefois régler la valeur de BLOCK pour minimiser les temps de copie. A priori 2000, c'est beaucoup trop peu (les blocks sont trop petits et donc sha1sum trop souvent appelée).

EDIT : @razer, le checksum du fichier destination est comparé au checksum du fichier source. Un diff sur des fichiers de 170 Go, c'est chaud ! Je me demande même si diff ne charge pas les deux fichiers en mémoire.  :Question: 

----------

## Jamesbch

@razer: Un miroir dans le sens oui mais j'ai mal utilisé le terme. Les données ne seront pas modifiées tant qu'elles ne seront pas transférée de disque1 à disque2. C'est bien là la différence. Pour l'instant je dois juste vérifier si les fichiers sont identiques. (La copie est déjà faite). Si les copies sont bonnes, que j'en serais sûr, je supprimerai les données sur le disque1 pour les laisser que sur le disque2, pour le moment. Les disques vont devoir se reposer quand même, sinon usage prématuré  :Confused: 

@Magic Banana: Oui sha1sum c'est bien, je ne sais ce que ça vaut en terme de vitesse comparé à MD4 (rsync --checksum) ou MD5 et CRC ?

Sinon ton code m'a l'air compliqué, je ne connais pas toutes ces commandes, wc ou expr etc... ?

Comme je l'ai peut-être mal dit, les données sont déjà copiées, dont il y a sûrement moyen d'utiliser ton script pour scanner l'arborescence complète et passer chaque fichier à sha1sum ?

Merci de ton code, il me sera sûrement utile.

Merci de vos réponses,

(rsync n'a pas fini il bloque un peu)

----------

## Magic Banana

Si les fichiers sont déjà copiés, c'est inutile. Fais un tar de chaque côté et lance sha1sum. Si tu tiens à savoir le temps qu'il met, fais précéder ta commande de "time". Ensuite, tu peux faire de même avec md5 (ou quoi que ce soit d'autre) et nous donner ces temps pour que l'on se couche moins bête ce soir.  :Wink: 

Sinon mon petit script n'est vraiment pas très compliqué. "wc -c" donne la taille d'un fichier. offset=`expr $offset + $BLOCK` est équivalent à let "offset += $BLOCK".

----------

## Jamesbch

Voilà, bon en fait je viens de confectionner cette ligne de rsync:

```
rsync -rbavh -n  /mnt/xfer/hdb1/ /mnt/
```

Pour l'instant j'utilise l'option "Dry run" (-n) qui me permet en théorie de voir ce qui va être copier (sans RIEN copier). Oui en théorie parce que si j'enlève -v, il n'y a rien (même si un fichier manque). Si je laisse -v, rsync me fais une bête liste de tous les fichiers. Pour l'instant avant d'enlever -n j'aimerais être sûr que ça soit bon, pour pas faire de bêtise. De toute façon j'ai monté mes deux partitions en ro pour être en sécurité.

Qu'est-ce qui me manque pour que rsync me dise si tel et tel fichier est juste ou faux etc...?

Peut-être que tu as une idée geekounet sur la manière d'utiliser rsync das mon cas ? Je te remercie déjà de m'avoir bien aiguillé.

 *Magic Banana wrote:*   

> Si les fichiers sont déjà copiés, c'est inutile. Fais un tar de chaque côté et lance sha1sum. Si tu tiens à savoir le temps qu'il met, fais précéder ta commande de "time". Ensuite, tu peux faire de même avec md5 (ou quoi que ce soit d'autre) et nous donner ces temps pour que l'on se couche moins bête ce soir. 
> 
> Sinon mon petit script n'est vraiment pas très compliqué. "wc -c" donne la taille d'un fichier. offset=`expr $offset + $BLOCK` est équivalent à let "offset += $BLOCK".

 

Comment ça un tar !?!? tu veux que je copie mes fichiers ENCORE DEUX FOIS 170GB ? c'est impossible, je ne peux pas !   :Shocked: 

1/ L'utilisation DES disques va les faire péter ! (très mauvaise idée)

2/ Je n'ai pas de place supplémentaire

----------

## Magic Banana

 *Jamesbch wrote:*   

> Comment ça un tar !?!?

 

Effectivement, je délre. En revanche, tu aurais tout intérêt à sauvegarder des tar.bz2 (ou mieux, des .7z), ne serait-ce que pour économiser de la place. Non ?

----------

## Jamesbch

Finalement, vu que j'aime bien programmer. J'ai fais un programme en Python faisons mes vérifications récursivement.

Le voici :

```
#!/usr/bin/python

# -*- encoding: utf8 -*-

import os

from sys import exit

import threading

from time import sleep

from string import replace

# A paramétrer pour vous

dir_base = "/mnt/disque1/"

dir_mir = "/mnt/disque2/"

def getSha(file):

 f = os.popen("sha1sum \"%s\"" % (file))

 try:

  p = f.readlines()

  return p[0].split(" ")[0]

 except:

  return False

def listAndCheck(dir):

 print "%s" % (dir)

 try:

  files = os.listdir(dir)

  for file in files:

   # enlève les caractères interdits

   file = replace(file, "$", "\$")

   if (os.path.isfile(dir+file) == True):

    checkFile(dir+file)

   elif (os.path.isdir(dir+file) == True):

    listAndCheck(dir+file+"/")

 except KeyboardInterrupt:

  exit()

def checkFile(file):

 file2 = dir_mir+replace(file, dir_base, "")

 if (os.path.isfile(file) == True):

  if (os.path.isfile(file2) == True):

   checksums = calculateMultiTh(file, file2)

   if checksums == False:

    print "!!! Cannot calculate SHA1SUM (for %s or %s)" % (file, file2)

    return False

   if (checksums[0] == checksums[1]):

    print "%s: SHA1SUM OK" % (file2)

    writeToFile("%s: SHA1SUM OK" % (file2), 1)

    writeToFile("%s\t%s\n" % (file, checksums[0]), 3)

    writeToFile("%s\t%s\n" % (file2, checksums[1]), 3)

   else:

    print "!!! %s: SHA1SUM FAILED (%s != %s)" % (file2, checksums[0], checksums[1])

    writeToFile("%s: SHA1SUM FAILED (%s != %s)" % (file2, checksums[0], checksums[1]), 2)

  else:

   print "!!! %s: NOT FOUND (Dest)" % (file2)

   writeToFile("!!! %s: NOT FOUND (Dest)" % (file2), 2)

 else:

  print "!!! %s: NOT FOUND (Base)" % (file)

  writeToFile("!!! %s: NOT FOUND (Base)" % (file), 2)

 return True

def calculateMultiTh(file1, file2):

 try:

  t1 = threadCalculate(file1)

  t2 = threadCalculate(file2)

  t1.start()

  t2.start()

  while True:

   if t1.isAlive() == False and t2.isAlive() == False:

    checksum1 = t1.getChecksum()

    checksum2 = t2.getChecksum()

    break

   else:

    sleep(0.1)

  if checksum1 != False and checksum2 != False:

   return [checksum1, checksum2]

  else:

   return False

 except:

  return False

class threadCalculate(threading.Thread):

 def __init__(self, _file):

  threading.Thread.__init__(self)

  self.file = _file

  self.checksum = False

 def run(self):

  try:

   self.checksum = getSha(self.file)

   return True

  except:

   return False

 def getChecksum(self):

  return self.checksum

def writeToFile(text, i):

 try:

  if i == 1: # STD

   hfile1.write(text+"\n")

  if i == 2: # ERR

   hfile2.write(text+"\n")

  if i == 3: # SHA

   hfile3.write(text+"\n")

 except:

  print "Cannot write to file"

  exit()

if __name__ == "__main__":

 # Logs

 hfile1 = open("./check-sha-std.log", "a")

 hfile2 = open("./check-sha-err.log", "a")

 hfile3 = open("./check-sha-chk.sha", "a")

 # C'est partit

 listAndCheck(dir_base)

 # Ferme les logs

 hfile1.close()

 hfile2.close()
```

Merci à tous, j'espère que ce script servira à quelqu'un un jour peut-être.

PS: J'ai améliorer le code et ajouté le support en multi thread  :Very Happy:  ça donne des temps bien meilleurs !

----------

