Boucle while sur retour commande sh distante

Bon je dis en fait tout dans le titre en un sens

Dans un script de sauvegarde, je vérifie le crc des fichiers locaux et distants pour m’assurer que le transfert s’est bien fait.
Pour cela je passe par une boucle while qui compare le crc local au crc distant de chaque fichier.
Si je fais cela sur des perif locaux, ça fonctionne (comparaison disque local et disque de sauvegarde sur USB)
Si je fais cela sur un serveur distant, c’est là que ça cafouille.
Du coup je me suis fait un petit script qui ne fait que retourner à chaque ligne le CRC du fichier distant et du fichier local.
Le script passe la première ligne sans problème, mais il ne va jamais à la seconde. Il s’arrête net et donc ne traite pas le restant.

Voilà ce que le bout de code donne :

#!/bin/bash

RAPPORT="mon_test.txt"
RCRC=""
LCRC=""
echo "" > ${RAPPORT}
cat /datas/send.list | while read line
do
        RCRC=""$(ssh -p22000 backup@ip_du_serveur "cksum /datas/serv_test/"${line}" | awk '{print \$1\$2}'")
        LCRC=""$(cksum /datas/${line} | awk '{print $1$2}')
        printf "fichier : "${line}"\n"
        printf "CRC local : "${RCRC}"\n"
        printf "CRC distant : "${LCRC}"\n"
done

si quelqun peut m’éclairer là dessus :confused:

edit:
voici un apperçu de ce que contient send.list

[code]test.txt
test.tgz
test.rar
test.html

[/code]

ce send.list est généré à la suite d’un rsync en mode verbose

...
rsync -avvvz --delete -e "ssh -p22000" ./ backups@ip_du_serveur:/datas/serv_test/ > /datas/rapport.log
cat /datas/rapport.log | grep "sender finished" | sed 's/sender.*finished //g' > /datas/send.list
printf "\n" >> /datas/send.list
...

il semblerait que la sortie de boucle soit due à l’envoie de la commande cksum sur le serveur distant par la commande ssh :confused:
j’ai beau essayer de me torturer la tête, je ne vois pas pourquoi

Et si au lieu de faire une connexion SSH par itération de ta boucle, tu créais un point de montage SSHFS temporaire ? Ensuite tu peux faire tes vérifications sur le filesystem “local”, ça serait sûrement plus fiable non ?

je pourrais oui, mais je trouve que monter un dossier distant sur un dossier local, et le démonter par la suite, c’est un peu lourd dans mon cas puisque je ne veux récupérer que le CRC et non copier des fichiers

Sinon oui j’aurai pu faire comme ça c’est ça ?

#!/bin/bash

RAPPORT="mon_test.txt"
RCRC=""
LCRC=""
echo "" > ${RAPPORT}

sshfs backup@ip_du_serveur:/datas/serv_test/ /data/remote/

cat /datas/send.list | while read line
do
        RCRC=""$(cksum /datas/remote/${line} | awk '{print $1$2}')
        LCRC=""$(cksum /datas/${line} | awk '{print $1$2}')
        printf "fichier : "${line}"\n"
        printf "CRC local : "${LCRC}"\n"
        printf "CRC distant : "${RCRC}"\n"
done

fusermount -u /data/remote

Oui c’est à ça que je pensais.
Cela dit tu soulèves un bon point auquel je n’avais pas pensé : le poids des fichiers à transférer pour pouvoir effectuer le checksum en local vs. la lourdeur de se connecter à chaque itération de la boucle.

Pour le problème de ta boucle qui s’arrête inopinément, j’ai pas d’idée non plus : en toute logique au pire il devrait renvoyer une valeur vide dans RCRC. L’option -e de sh/bash n’est pas activée par hasard (ss64.com/bash/set.html) ?

[quote=“syam”]Oui c’est à ça que je pensais.
Pour le problème de ta boucle qui s’arrête inopinément, j’ai pas d’idée non plus : en toute logique au pire il devrait renvoyer une valeur vide dans RCRC. L’option -e de sh/bash n’est pas activée par hasard (ss64.com/bash/set.html) ?[/quote]
je n’y avais pas pensé oui… mais après test, cela ne change rien :confused:
(j’ai rajouté un “set +e” en début de script pour désactiver l’option)

Bonjour,

J’ajouterai l’option -x à ton script pour avoir le détail de son exécution.

Par ailleurs, pour éviter de faire autant de connexion ssh qu’il y a de fichier, je ferai quelque chose comme ceci :

{ ssh -T -p22000 backup@ip_du_serveur<<EOF
while read
do
  cksum "/datas/\${REPLY}"
done <<SSH_EOF
$(</datas/send.list)
SSH_EOF
EOF
} | awk '{print $1$2}'

…qui te donnera en une seule connexion, le checksum de tous tes fichiers
(note l’utilisation de l’option -T pour la connexion ssh)

A la bourrin ?

[code]liste=’/datas/send.list’
tmpdir=$(mktemp -d)

sed ‘s|^|/datas/remote/’ “${liste}” > “${tmpdir}/files_dist"
ssh backup@ip_du_serveur cksum $(<”${tmpdir}/files_dist") > “${tmpdir}/res_dist”

sed ‘s|^|/datas/’ “${liste}” > “${tmpdir}/files_loc"
cksum $(<”${tmpdir}/files_loc") > “${tmpdir}/res_loc”

sort ${tmpdir}/res_* | uniq -u
#ou awk ‘{print $3" "$1$2}’ ${tmpdir}/res_* | sort | uniq -u

rm -rf “${tmpdir}”[/code]
Pas de boucle, parallélisable facilement, une seule connexion ssh et assez simple, on peut faire mumuse et virer certaines commandes extérieures au shell ainsi que des fichiers temporaires pour le plaisir (toutes avec zsh !).

…ce qui donne :

#!/bin/bash
fichiers=( $(</datas/send.list) )
sort <(ssh -T -p220000 backup@ip_du_serveur cksum "${fichiers[@]}/#//datas/}") <(cksum "${fichiers[@]}/#//datas/}") | uniq -u

edit : remplacement de ^ par # dans l’expression “${fichiers[@]}/#//datas/}”

yeah
merci bien pour votre aide à tous :smiley: