Travail terminé, corrections

Alors, prenons l’exemple (je trouve que c’est toujours plus parlant) le plus simple : une fonction qui affiche les paramètres :

#!/bin/bash
# fonction qui affiche tous les paramètres via leur "numéro"
# Objectif : introduction de $1, $2, $3 ..., $9
function afficheParams1_9()
{
  printf "param 1 = %s\n" "$1"
  printf "param 2 = %s\n" "$2"
  printf "param 3 = %s\n" "$3"
  printf "param 4 = %s\n" "$4"
  printf "param 5 = %s\n" "$5"
  printf "param 6 = %s\n" "$6"
  printf "param 7 = %s\n" "$7"
  printf "param 8 = %s\n" "$8"
  printf "param 9 = %s\n" "$9"
}

# function qui affiche tous les paramètres Version 1
# objectif : introduction de $# et de shift
function afficheAllParamsV1
{
# $# = nombre de paramètres
# il faut comprendre la condition comme ceci : on initialise i à 1, on boucle tant que le nombre de paramètre est > 0 et à chaque boucle on incrémente i de 1
  for((i=1;$#>0;i++))
  do
    printf "param %d = %s\n" $i "$1"
    shift # ici on décale les paramètre d'une position : le 2nd vient en position 1, le 3eme en 2, le 4eme en 3 etc... 
  done
}

# function qui affiche tous les paramètres Version 2
# objectif : introduction de $@ 
function afficheAllParamsV2
{
   # les paramètres positionnels sont en fait contenu dans un tableau. En bash, il est possible de faire référence à [b]tous[/b] les éléments d'un tableau via le caractère @ : "${nomTableau[@]}". Pour les paramètres positionnels, "$@" correspond à la contraction de cette forme et cela correspond à "$1" "$2" ... "$i"  

  i=0
  for element in "$@"
  do
    ((i++))
    printf "param %d = %s\n" $i "$element"
  done
}

# function qui affiche tous les paramètres Version 3
# objectif : introduction de $* 
function afficheAllParamsV3
{
   # Il existe une autre forme d'accès à l'ensemble des éléments des paramètres positionnels : $*
   # il y a une différence notable avec $@ :
   # $* équivaut à $1 $2...$i
   # et "$*" équivaut à "$1 $2...$i"

  i=0
  for element in $*
  do
    ((i++))
    printf "param %d = %s\n" $i "$element"
  done
}

afficheParams1_9 Valeur1 "Valeur 2" "" "" "*" "encore une valeur"
afficheParams1_9 "" "" "" "" "" "" "" "" '9 !' "et 10"

echo "afficheAllParamsV1"
afficheAllParamsV1 Valeur1 "Valeur 2" "" "" "*" "encore une valeur"
echo "**************"
afficheAllParamsV1 "" "" "" "" "" "" "" "" '9 !' "et 10"

echo "afficheAllParamsV2"
afficheAllParamsV2 Valeur1 "Valeur 2" "" "" "*" "encore une valeur"
echo "**************"
afficheAllParamsV2 "" "" "" "" "" "" "" "" '9 !' "et 10"

echo "afficheAllParamsV3"
afficheAllParamsV3 Valeur1 "Valeur 2" "" "" "*" "encore une valeur"
echo "**************"
afficheAllParamsV3 "" "" "" "" "" "" "" "" '9 !' "et 10"

pour info il existe une forme particulière à la structure for variable in valeur1 valeur2 … valeuri : for variable
…tout simplement ! et cela équivaut à for variable in “$@”

voilà, je te laisse faire un copier/coller dans un script pour tester tout ça et voire la différence entre la V2 et la V3 :wink:

edit : le but de tout ça est de t’inciter à faire une fonction qui prend en argument le statut d’exécution du rsync et le dossier qui a été sauvegardé et d’y faire le test “if” dedans.

edit2 : désolé de ne pas être plus réactif mais j’ai pas mal de taf et je suis seul à m’occuper des enfants en ce moment …

Ne t’excuse pas, tu passes déjà assez de temps avec moi et je t’en remercie.
De plus, je ne suis pas toujours devant mon ordi et ça me donne parfois le temps de la réflexion.
C’est quand même en découvrant bash (que je ne croyais pas aussi complet) que je me rends compte de la différence qu’il y a entre ‘avoir 50 ans’ et en avoir 75. Au premier de ces âges, j’avais appris en peu de temps le basic, le GFA, Pascal et commencé le C. Aujourd’hui, je vois que ça va beaucoup moins vite à rentrer :unamused:
Je vais déjà essayer de digérer tout ce que tu me présentes dessus et on verra si j’arrive à assimiler. Je pense toutefois que ça sera dur.
Merci encore.

Bon, je n’arrive pas à comprendre :
1/ les paramètres que je dois envoyer à la fonction
2/ comment écrire ce que la fonction doit exécuter.
Je vais te demander de le faire pour moi et ptet que ça va m’ouvrir les yeux.
Sois gentil de ne rien remplacer (pas de "param1, param2,etc) mais d’employer les données suivantes :

function testSauvegarde()
{
???
}
données actuelles :

read -p "prêt pour la sauvegarde ? o/* : " onyva if [ "$onyva" = o ] then sudo rsync -av --del --backup --backup-dir="$controle" --exclude-from="$exclure" / "$sauve" if (( $? == 0 )) then printf "\nSauvegarde de / : ok\n" else printf "\nErreur lors de la sauvegarde de /\n" >&2 exit 1 fi sudo rsync -av --del --backup --backup-dir="$controle_user" --exclude-from="$exclure_user" ~/ "$sauve_user" if (( $? == 0 )) then printf "\nSauvegarde du dossier %s : OK\n" ~/ else printf "\nErreur lors de la sauvegarde de %s\n" ~/; >&2 exit 1 fi else exit 1 fi

pas de soucis mais pour des raisons de compréhension, je préfère intégrer des nouvelles variables au sein de la fonction :

function testSauvegarde()
{
 # ici on récupère le paramètre n°1 passé à la fonction (c'est le statut d'exécution de l'instruction sudo rsync)
  statutRsync="$1" 

 # ici on récupère le paramètre n°2 qui est le nom de dossier que l'on a sauvegardé
 dossierSauve="$2"
  
 # test si ça s'est bien passé
 if ((statutRsync > 0))
 then
   # ce n'est pas le cas, on affiche un message puis on quitte le script
   printf "\nErreur lors de la sauvegarde de %s\n" "${dossierSauve}" >&2
   exit 1
 fi
 # puisque l'on arrive à cette ligne, c'est que la sauvegarde s'est bien déroulée. on l'indique (ça suffit)
 printf "\nSauvegarde de %s : ok\n" "${dossierSauve}"
}

edit : suppression de l’intégration de la fonction dans ton code … je te laisse le soin d’essayer de la faire

Non, excuse-moi, je ne comprends rien de rien.
Je suis bouché à ce truc !
Je préférerais que tu me l’écrive complètement avec les données que j’ai, je pense que c’est la seule façon pour moi de comprendre.

hummm, je pense que tu ne vois pas le lien avec ton script.
je te donne l’intégration de la fonction au sein de ton script :

#!/bin/bash

function testSauvegarde()
{
# ici on récupère le paramètre n°1 passé à la fonction (c'est le statut d'exécution de l'instruction sudo rsync)
  statutRsync="$1"

# ici on récupère le paramètre n°2 qui est le nom de dossier que l'on a sauvegardé
dossierSauve="$2"
 
# test si ça s'est bien passé
if ((statutRsync > 0))
then
   # ce n'est pas le cas, on affiche un message puis on quitte le script
   printf "\nErreur lors de la sauvegarde de %s\n" "${dossierSauve}" >&2
   exit 1
fi
# puisque l'on arrive à cette ligne, c'est que la sauvegarde s'est bien déroulée. on l'indique (ça suffit)
printf "\nSauvegarde de %s : ok\n" "${dossierSauve}"
}

ddext="/dev/sdb9"
ddext2="/dev/sdb10"
mount_rep="/mnt/autre"
systeme_fich="ext3"
systeme_fich2="ext2"
controle="/home/controle"
controle_user="/home/controle-ricardo"
exclure="/root/exclure"
exclure_user="/home/ricardo/.exclure"
sauve="/mnt/autre/sauve"
sauve_user="/mnt/autre/sauve-ricardo"

#-----------------------------------------------------------------------------

[ -e "$ddext" ] && [ -e "$ddext2" ] || { echo "Le DDext ne repond pas !" >&2; exit 1; } # teste l'existence des partitions de sauvegarde
   
mkdir -p "$mount_rep" || { echo "Le dossier de montage n'existe pas !" >&2; exit 1; }   # teste l'existence du dossier de montage

read -p 'sauve ou sauve2 ? : ' part    # choix de la sauvegarde
case $part in
     sauve)
          sudo mount -t "$systeme_fich" "$ddext" "$mount_rep"
     ;;
     sauve2)
          sudo mount -t "$systeme_fich2" "$ddext2" "$mount_rep"
     ;;
     *)     
          echo "mauvaise entree" >&2; exit 1;
     ;;
esac

echo  -e "\033[4mCONTENU de la CORBEILLE\033[0m\n"     
if [ -e ~/.local/share/Trash/files ]   # teste si la corbeille est pleine (existence de /files)
then
   ls ~/.local/share/Trash/files   # si pleine, liste les fichiers qu'elle contient
   read -p "on peut la vider  ? o/* : " corbeille   
      if [ "$corbeille" = o ]
      then
         rm -rf ~/.local/share/Trash/*
         echo -e "\033[4mCORBEILLE VIDEE\033[0m"
      fi
else
   echo "La corbeille est vide"
fi

read -p "prêt pour la sauvegarde ? o/* : " onyva
   if [ "$onyva" = o ]
   then
      sudo rsync -av --del --backup --backup-dir="$controle" --exclude-from="$exclure" / "$sauve"
      # test de l'état de la sauvegarde
      # 1er paramètre : $?=statut de la dernière commande, c.a.d le rsync
      # 2nd paramètre : / = dossier à sauvegarder
      # la fonction se charge de quitter le script si la sauvegarde est ko
      testSauvegarde $? /

      sudo rsync -av --del --backup --backup-dir="$controle_user" --exclude-from="$exclure_user" ~/ "$sauve_user"

      testSauvegarde $? ~/
   else
      exit 1
   fi

sudo umount "$mount_rep"

j’ai volontairement supprimé la dernière ligne de ton code : le “exit” tout seul
en effet, le script devrait retourner le statut de la dernière commande car tu ne vérifies pas si elle s’est bien passée (un “exit” tout seul retourne 0 comme statut).

C’est plus clair, en effet !
Je voyais ça de façon plus complexe car je pensais que chaque variable de la ligne était un argument. Je ne pensais pas que le ‘exclude’ fasse partie de la commande et je voulais ajouter le dossier de sauvegarde, ce qui me faisait 4 arguments mais je ne savais pas comment les ranger dans la boîte :unamused:

Là je dois sortir mais j’étudie ça de façon plus approfondie ce soir car je veux être sûr de comprendre complètement.
Faut être patient avec les vieux :unamused:

rien ne t’empêche d’ajouter d’autres arguments à la fonction et de les y exploiter pour affichage (ou autre) !

ma patience n’est rien comparée à l’effort intellectuel que tu donnes ! je trouve ça remarquable que quelqu’un de ton âge s’intéresse à l’informatique comme tu peux le faire. Généralement, à cet âge, les gens ne font que naviguer sur le net, utiliser sa messagerie, un peu de bureautique et stockage de fichier (images/vidéos). :023

Je viens donner mon petit grain de sel. C’est une histoire de style, mais j’aime bien faire comme ça :

die_on_error() { if ( $? != 0 ) { printf "$@\n" exit 1 } }
à utiliser ainsi :

cmd die_on_error 'Erreur de la commande : cmd !'

ou alors plus dans l’esprit de perl

die(){ printf "$@\n" exit 1 }
à utiliser ainsi

Remarque : J’utilise $@ qui représente l’ensemble des arguments passés à la fonction.
Si on appel ma fonction die() ainsi :

alors dans la fonction die $@ vaudras “$1 $2”. Là où c’est intéressant c’est que quand $@ est protégé par des double guillemets ("), il va être interprété comme “$1” “$2”.

Si ce n’est pas le comportement souhaité il faut utiliser $@, car “$@” seras interprété comme “$1 $2” (dans le cas où l’on passe deux arguments à la fonction die()).

Là où c’est intéressant c’est que du coup ma fonction die() peut s’utiliser comme printf() et ce code marche :

Ça y est, je crois avoir tout assimilé.

[quote=“Totor”]
j’ai volontairement supprimé la dernière ligne de ton code : le “exit” tout seul
en effet, le script devrait retourner le statut de la dernière commande car tu ne vérifies pas si elle s’est bien passée (un “exit” tout seul retourne 0 comme statut).[/quote]
Si je comprends bien, la règle c’est de tester TOUTES les commandes ?
Je propose donc ça pour la fin :

sudo umount "$mount_rep"
	if (( $? == 0 ))
		then
  		printf "\n"$mount_rep" bien démonté\n"
	else
  		printf "\nErreur lors du démontage de "$mount_rep"\n" >&2
  		exit 1
	fi
exit 0

Il n’y a pas vraiment de règle. à mon sens, c’est juste une question de fiabilisation du comportement.

si l’un des 2 rsync n’a pas fonctionné (du fait d’un mount n’ayant pas abouti car partition hs ou parce qu’il y a un problème de droit sur les dossiers), l’objectif final n’est pas atteint et l’on ne sait pas trop ce qui a été sauvegardé.

en revanche, si le umount n’a pas fonctionné, c’est beaucoup moins grave et ça ne remet pas en cause le traitement…

Ben si le montage a foiré, aucune sauvegarde ne sera faite puisqu’on sort avant :

[quote]
mkdir -p “$mount_rep” || { echo “Le dossier de montage n’existe pas !” >&2; exit 1; } [/quote]

En définitive, la fin que je propose est utile ou pas ?

La ligne que tu as donné contenant “mkdir” ne garantie en rien le montage de la partition : elle a juste pour rôle de créer le dossier (+ traitement d’erreur) où la partition sera montée.
ce sont les 2 lignes “sudo mount …” qui font le montage !!! (dont tu ne vérifies pas la bonne exécution)
du coup, oui, les rsync peuvent ne pas fonctionner car la partition n’est pas montée !!!

Pour ta proposition de fin, je ne pense pas qu’elle soit utile. En effet, le “umount” est la dernière instruction de ton script et qu’en cas d’erreur :

  • elle affichera le “pourquoi du comment” de ce qui n’a pas été donc tu en seras informé
  • elle chargera de spécifier le statut d’exécution du script (si on ne met pas de “exit” ensuite)
  • de plus, une erreur de démontage ne remet pas en cause ta sauvegarde.

[quote=“Totor”]La ligne que tu as donné contenant “mkdir” ne garantie en rien le montage de la partition : elle a juste pour rôle de créer le dossier (+ traitement d’erreur) où la partition sera montée.
ce sont les 2 lignes “sudo mount …” qui font le montage !!! (dont tu ne vérifies pas la bonne exécution)
du coup, oui, les rsync peuvent ne pas fonctionner car la partition n’est pas montée !!![/quote]En effet !
J’ai fait un test en provoquant une erreur sur le montage de ‘sauve’.
Il m’indique bien qu’il y a une erreur mais il ne sort pas pour ça.
J’ai essayé de réparer cet oubli en ajoutant aux lignes de montage, une sortie comme suit et le test est positif.
Est-valable ?
est-ce indispensable d’ajouter aussi le message explicatif, sachant qu’il est mentionné en cas d’erreur de montage

sauve ou sauve2 ? : sauve mount: wrong fs type, bad option, bad superblock on /dev/sdb10, missing codepage or helper program, or other error In some cases useful info is found in syslog - try dmesg | tail or so ricardo@sid-sda8:$

[quote]case $part in
sauve)
sudo mount -t “$systeme_fich” “$ddext2” “$mount_rep” || >&2; exit 1;
;;
[/quote]
en rouge pour provoquer l’erreur
en bleu pour ajouter une sortie


Autre chose :
Plusieurs questions concernant la fonction ‘testSauvegarde’

1/ je suppose que toutes les annotations ne seront pas à placer dans le script définitif, et que tu ne les a faites que pour moi dans un but pédagogique ?

2/ est-il indispensable de “récupérer” les paramètres (statutRsync="$1") ou, là aussi, c’est pour que je comprenne plus facilement ?
Si ce n’est pas indispensable, est-ce qu’il faudrait écrire la condition ainsi : if (("$1" > 0)) … printf … “$2” >&2 , etc. ?

3/ signification du ‘%s’ : c’est la commande de positionnement de ce qui suit après : “${…}” ? c’est spécifique à printf ? Je suppose qu’on ne peut pas placer directement dans les premiers “”, comme avec ‘echo’ ?

non, pas du tout

exactement !

[quote]case $part in
sauve)
sudo mount -t “$systeme_fich” “$ddext2” “$mount_rep” || >&2; exit 1;
;;
[/quote]
ouh là… y’a erreurs :

  • normalement, il n’y pas besoin de rediriger le texte vers la sortie d’erreur car “mount” le fait déjà
  • il ne faut pas de “;” avant le “exit 1” sinon le “exit 1” sera executé à tous les coups

exactement :wink: c’est à toi de voire pour les commentaires. Il est bon d’en mettre mais judicieusement : pas de commentaire ne facilite pas la maintenant et trop de commentaire ne facilite pas la lisibilité du code

tout à fait. J’ai utilisé des variables pour te faciliter la compréhension.

Oui, c’est bien la “commande de positionnement” et c’est spécifique à printf. Et si, on peut directement mettre dans les guillemets.
mais il ya bien des avantages à printf que je ne vais pas détailler mais juste donner un exemple à tester :

printf "%s\n" 1 2 3 4
echo 1 2 3 4

Ok, merci pour tout !
Je suis content de mes déductions, c’est la preuve (pour moi) que j’arrive à comprendre à peu près.
Je referai une ébauche complète ce soir.
:006

EDIT :
efficace, l’exemple :023

Ne pourrait-on pas intégrer cette dernière ligne (en bleu) à la condition avec un else ? Ça me semble plus “causant”.

if ((statutRsync > 0)) then printf "\nErreur lors de la sauvegarde de %s\n" "${dossierSauve}" >&2 exit 1 else printf "\nSauvegarde de %s : ok\n" "${dossierSauve}" fi

[size=150]C’EST TESTÉ = BON ![/size]

Avec les fioritures :smiley:

[code]
#!/bin/bash

BEGIN INIT INFO

Nom du script : sauvegarde

Auteur : Ricardo, aidé de l’équipe de ‘debian-fr.org

Date de création : juillet 2011

Utilité : faciliter les sauvegardes

Version : cette version est écrite pour l’utilisation avec deux partitions de sauvegarde, à alterner dans le temps.

#+ Il est souhaitable que ces partitions soient sur un DD différent de celui qui abrite le système

Pré-requis : voir tuto = http://www.debian-fr.org/sauvegarde-clonage-d-une-sid-t25179.html

Description : script permettant d’effectuer, régulièrement et de façon simple, les sauvegardes de son système

Droits : entièrement libres mais en cas de copie, la citation de “debian-fr.org” nous serait agréable

Modifié le :

Objet de la modification :

END INIT INFO

function test_sauvegarde()
{

Teste si la sauvegarde a abouti (premier paramètre = 0), sinon, on sort.

if (("$1" > 0))
then
	printf "\nErreur lors de la sauvegarde de %s\n" "$2" >&2
	exit 1
else
	printf "\nSauvegarde de %s : OK\n" "$2"
fi

}

#-----------------Variables-------------------
ddext="/dev/sdb9"
ddext2="/dev/sdb10"
mount_rep="/mnt/autre"
systeme_fich=“ext3"
systeme_fich2=“ext2"
controle=”/home/controle"
controle_user=”/home/controle-ricardo"
exclure="/root/exclure"
exclure_user="/home/ricardo/.exclure"
sauve="/mnt/autre/sauve"
sauve_user="/mnt/autre/sauve-ricardo"
#---------------------------------------------

Teste l’existence des partitions de sauvegarde et celle du dossier de montage, sinon, on sort avec erreur 1.

[ -e "$ddext" ] && [ -e "$ddext2" ] || { echo "Le DDext ne répond pas !" >&2; exit 1; } 

mkdir -p "$mount_rep" || { echo "Le dossier de montage n'existe pas !" >&2; exit 1; }	

Choix de la sauvegarde. Si le montage ne s’effectue pas, on sort avec erreur 1.

read -p 'sauve ou sauve2 ? : ’ part
case $part in
sauve)
sudo mount -t “$systeme_fich” “$ddext” “$mount_rep” || exit 1;
;;
sauve2)
sudo mount -t “$systeme_fich2” “$ddext2” “$mount_rep” || exit 1;
;;
*)
echo “mauvaise entrée” >&2; exit 1;
;;
esac

Teste si la corbeille est pleine (pésence de fichier(s) dans … /files), si elle l’est, liste les fichiers qu’elle contient

echo -e "\033[4mCONTENU de la CORBEILLE\033[0m\n"
if [ -e ~/.local/share/Trash/files/ ]
then
ls ~/.local/share/Trash/files
read -p "on peut la vider ? o/* : " corbeille
if [ “$corbeille” = o ]
then
rm -rf ~/.local/share/Trash/*
echo -e "\033[4mCORBEILLE VIDÉE\033[0m"
fi
else
echo "La corbeille est vide"
fi

Test de l’état de la sauvegarde avec la fonction “test_sauvegarde”, qui se chargera de quitter le script si celle-ci est KO

1er paramètre : $? = statut de la dernière commande, c.a.d le rsync

2nd paramètre : / puis ~/ = dossier à sauvegarder

read -p “prêt pour la sauvegarde ? o/* : " onyva
if [ “$onyva” = o ]
then
sudo rsync -av --del --backup --backup-dir=”$controle" --exclude-from="$exclure" / "$sauve"
test_sauvegarde $? /

  		sudo rsync -av --del --backup --backup-dir="$controle_user" --exclude-from="$exclure_user" ~/ "$sauve_user"
  		test_sauvegarde $? ~/
else
  		exit 1
fi

Pas de test pour le démontage, si problème, l’alerte est suffisamment explicite.

sudo umount “$mount_rep”[/code]

Verdict ?

ben ça me parait pas mal :wink:

maintenant que tu vois comment utiliser les paramètres, auras-tu le courage de revenir sur la partie abandonnée ?

[quote=“Totor”]ben ça me parait pas mal :wink:

maintenant que tu vois comment utiliser les paramètres, auras-tu le courage de revenir sur la partie abandonnée ?

[quote=“Totor”]
A voire pour la suite :

  • une option -h affichant le synopsis serait pas mal
  • plutôt que d’avoir une interaction avec l’utilisateur, ajouter des paramètres des dossiers à sauvegarder, du point de montage et de la partition à monter, suppression ou non de la corbeille, des fichiers de contrôle etc… serait nettement un plus. En effet, cela te permettrai d’ordonnancer ton script ! (rien n’empêche d’ajouter une option pour forcer l’interaction :whistle: ) Et puis, pour la même raison que pour le ~ : tout le monde n’a pas le même disque dur avec les mêmes partitions !
    [/quote][/quote]

OK, j’étudierai ça mais d’abord, je vais corriger mon tuto et y intégrer ce script.
Merci pour tout.
La suite dans quelques jours :006

[size=150]EDIT :[/size]
Correction : enlevé le signe ’ *

[quote]# Teste si la corbeille est pleine (pésence de fichier(s) dans … /files), si elle l’est, liste les fichiers qu’elle contient
echo -e “\033[4mCONTENU de la CORBEILLE\033[0m\n”
if [ -e ~/.local/share/Trash/files/[size=150]*[/size] ] [/quote]