# [BASH] Copie de fichier / controle d'intégrité (resolu)

## anonjoe

Bonjour,

Je voudrais savoir si il existe une alternative a la commande "cp", qui me permettent de copier un gros fichier (+ de 6 Go) d'un disque dur vers un autre, de façon a être sur que l'intégrité du fichier soit respecté.

J'ai pensé qu'utilisé scp pourrais répondre a mes besoin, mais je n'en suis pas sur.

MerciLast edited by anonjoe on Mon Nov 12, 2007 2:21 pm; edited 1 time in total

----------

## GentooUser@Clubic

Heu SCP c'est pas pour le transfert sécurisé via SSH ?

un md5sum du fichier source puis de la copie, tu peut mettre ça dans un script pour automatiser le tout. Mais pour un fichier de 6go le calcul risque d'être assez long !

Sinon rsync ne vérifie pas l'intégrité des données ?

----------

## anonjoe

 *GentooUser@Clubic wrote:*   

> Heu SCP c'est pas pour le transfert sécurisé via SSH ?

 

Si la copie se fera dans un tunnel ssh, mais c'est pas grave je ne pense pas que ca ralentisse la copie sensiblement. Et étant donné que c'est prévu pour du réseau je me dis que le controle de l'intégrité doit être meilleur qu'avec cp.

----------

## guilc

 *anonjoe wrote:*   

>  *GentooUser@Clubic wrote:*   Heu SCP c'est pas pour le transfert sécurisé via SSH ? 
> 
> Si la copie se fera dans un tunnel ssh, mais c'est pas grave je ne pense pas que ca ralentisse la copie sensiblement. Et étant donné que c'est prévu pour du réseau je me dis que le controle de l'intégrité doit être meilleur qu'avec cp.

 

Si, passer par scp ça ralentit beaucoup ! et ton CPU en prend un sacré coup. C'est déjà super difficile de remplir un lien 100Mbits en scp, a moins d'avoir une machine super costaud, alors des disques physiques sans réseau au milieu...

cp ASSURE l'intégrité, parceque les drivers de FS du noyaux ne fournissent pas de la cochonnerie ! pas besoin de plus.

Au pire, tu peux faire des md5sum, mais le fait que la commande cp ne balance pas d'erreur d'IO est suffisant pour affirmer que le fichier n'est pas endommagé...

Ca serait plutot très grave que cp ne soit pas fiable. Au delà de la copie, ça signifierait que les lectures/écritures sur les disques ne sont pas fiable, et ce n'est carrément pas admissible... (linux serait déjà mort dans ce cas...)

----------

## loopx

d'accord avec toi, mais j'ai déjà eu des probz:

tu copie via cp sur un dur, tout va bien ... le problème se situe à la relecture => trop tard ... Faut relire le fichier pour etre sur ...

----------

## anonjoe

En fait j'ai eu un soucis sur une iso de 6Go que j'ai copier sur un disque NTFS monter par ntfs-3g.

J'men suis apperçu trop tard.

Au pire je ferais un checksum ap la copie, mais si c'est foireux faut tout recommencer...

----------

## Magic Banana

Je pense que faire un simple cp est suffisant. Utilise md5 pour te rassurer si tu le souhaites. Fait attention au système de fichiers vers lequel tu copies. Certains (FAT32 par exemple) ne peuvent héberger ton fichier en un morceau.

Si tu tiens tellement a l'envoyer par petits morceaux (chacun vérifié par md5), fais toi un script bash à base de dd (avec les opérandes skip, seek et count). Je peux même te le faire si tu y tiens. Mais je crois vraiment que cp fera la job sans problème.

----------

## loopx

le md5 est une très bonne solution en fait, ca va forcer l'ordi à relire la copie  :Wink:   ce qui détecterais le problème que j'ai eu   :Cool: 

----------

## Magic Banana

Bon j'étais motivé pour te pondre un script. Le voilà donc :

```
#!/bin/bash

BLOCK=2000

CHECKSUM="sha1sum"

if [ -z "$2" ]

then

    echo "Usage: safe-cp src dest"

    exit 64

fi

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

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

    dd if="$2" of="$2.tmp" skip=$offset count=$BLOCK 2> /dev/null

    if [ `$CHECKSUM "$1.tmp" | awk '{print $1}'` = `$CHECKSUM "$2.tmp" | awk '{print $1}'` ]

    then

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

   offset=`expr $offset + $BLOCK`   

    fi

done

rm "$1.tmp" "$2.tmp"

exit 0

```

Tu peux changer la fonction de checksum utilisée en changeant le contenu de la variable CHECKSUM. Par exemple tu peux y mettre "md5sum". Nettement plus important, tu peux changer la taille des segments qui sont envoyé et vérifiés à mesure à l'aide de la variable BLOCK. Comme son nom l'indique il s'agit d'une taille en block (sur mon ext3 un bloc mesure 512 octets). Il s'agit de deviner la valeur optimale en fonction du taux d'erreur. Pas facile... Si tu transmets des tout petits blocks tu vas faire énormément de checksums et le temps de transfert sera énormément augmenté. Si le taux d'erreur fait qu'il y a toujours une erreur dans chaque segment envoyé, la copie n'avancera pas.

Donne en moi des nouvelles !  :Wink:  [/code]

----------

## Magic Banana

Bon j'en ai pas dormis cette nuit de ce script !  :Laughing:   En fait je ne suis pas certain que la taille d'un bloc soit identique sur n'importe quel système de fichiers, sur n'importe quel disque... mais je crois que si. Essaie tout de même d'envoyer d'abord un petit fichier (choisis BLOCK de manières à ce qu'il y ait plusieurs segments) et voit si tout va bien (si ça va mal, le script ne s'arrêtera pas tout seul : Ctrl + C).

Sinon, il y avait un problème dans le cas où tu copiais vers un fichier existant et de taille supérieure (OK vue la taille de ton fichier ce serait étonnant). J'ai rajouter le rm qui va bien en début de script. Enfin j'ai laissé l'approche fichiers temporaires pour des pipes. Je pensais au début que cela éviterait de copier trois fois le fichier (deux sont des copies de contôle d'intégrité) mais en fait non ! Enfin, pour être plus précis, je crois que le bash fixe une limite quand à la taille d'un pipe (et que c'est 8 blocs par défaut) et que tu ne veux pas rester sous cette limite (trop de petits segments).

Bref, voilà le script corrigé :

```
#!/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

```

----------

## guilc

 *anonjoe wrote:*   

> En fait j'ai eu un soucis sur une iso de 6Go que j'ai copier sur un disque NTFS monter par ntfs-3g.
> 
> J'men suis apperçu trop tard.

 

Bah voila, quand on utilise du bricolage aussi... C'est pas de la même qualité que les drivers inclus dans le noyau ça, on ne peut pas lui demander la même fiabilité... ET dans ce cas précis, scp ne changera strictement rien, c'est le driver au moment de l'écriture qui a fait les erreurs, pas cp...

----------

## kwenspc

 *guilc wrote:*   

> C'est pas de la même qualité que les drivers inclus dans le noyau ça

 

Les drivers NTFS dans le noyau ils ne savent pas bien écrire sur du ntfs il me semble, en tout cas ça foire encore plus facilement la-dite partoche.

----------

## GaMeS

 *kwenspc wrote:*   

> 
> 
> Les drivers NTFS dans le noyau ils ne savent pas bien écrire sur du ntfs il me semble, en tout cas ça foire encore plus facilement la-dite partoche.

 

+1, les drivers disponible dans portage sont régulièrement mis à jour ce qui n'est pas le cas dans le noyau.

----------

## guilc

Pardon, je me suis mal fait comprendre  :Laughing: 

Je pensais aux "VRAIS" drivers de FS en écrivant ça, du genre ext, XFS, Reiserfs, JFS... certainement pas le driver NTFS du noyau   :Wink: 

----------

## Bapt

C'est peut être une connerie mais pourquoi ne pas la copie par rsync ? ça marche très bien en local, et s'assure de l'intégrité.

----------

## Magic Banana

 *Bapt wrote:*   

> C'est peut être une connerie mais pourquoi ne pas la copie par rsync ? ça marche très bien en local, et s'assure de l'intégrité.

 

Euh... C'est pas que je suis mégalo mais le script que j'ai pondu fait exactement ce qu'il veut et rien d'autre (man dd peut vous aider à vous en convaincre si vous ne me faites pas confiance) : au lieu de copier le fichier entier et de vérifier a posteriori de l'intégrité, le fichier est envoyé par morceau (de taille paramétrable via la variable BLOCK). Chaque morceau est testé pour voir si sa copie s'est bien passé. Si c'est le cas on passe à la suite sinon on recommence avec le même.

Utiliser des commandes utilisant des protocoles de transfert sur réseau (ftp, scp, etc.) ou destinées à n'envoyer qu'un diff d'un fichier (rsync) ne peut qu'être moins efficace et je ne suis vraiment pas sûr que des tests d'intégrités sur des morceaux de fichiers soient réalisés.

----------

## El_Goretto

Comme autre fonction de vérification, t'as aussi les fichiers par2: même inconvénient, faut relire le fichier, mais l'avantage c'est que ça inclut les mécanismes de correction d'erreur (donc pas besoin de rererecopier).

Et respect à Magic Banana  :Smile: 

----------

## anonjoe

Ouai franchement c'est nickel ton script, encore merci

Petite annecdote je me suis apperçu qu'en fait c'etait mon iso original qui était corrompu   :Rolling Eyes: 

----------

## Magic Banana

 *anonjoe wrote:*   

> Ouai franchement c'est nickel ton script, encore merci

 

De rien.

 *anonjoe wrote:*   

> Petite annecdote je me suis apperçu qu'en fait c'etait mon iso original qui était corrompu  

 

Arf!  :Laughing: 

----------

