Traduction(s) : aucune
Rsync est connu pour être le parfait utilitaire de mise à niveau d'une sauvegarde par rapport à un original. Cet outil est rapide puisqu'il permet de ne recopier sur la sauvegarde que les changements effectués depuis la dernière sauvegarde (grâce à un algorithme de comparaison).
L'option --link-dest de rsync a un avantage considérable, elle permet de lier en lien dur la sauvegarde avec une ancienne sauvegarde. L'avantage du lien dur est qu'il permet à rsync de mettre à jour les fichiers qui ont changés mais de lier ceux qui n'ont pas évolué avec leur ancienne version (afin d'économiser la place sur le disque dur et donc de pouvoir mettre en place un système de roulements de sauvegardes).
Utilisation de Rsync pour historiser les sauvegardes
Avant d'attaquer la description de ce qu'il faut mettre en place pour y parvenir, décrivons un peu mieux "l'architecture" :
- Les sauvegardes sont accueillies dans mon exemple par le répertoire /srv/rsync du serveur ;
- Il peut y avoir différents clients envoyant au serveur, lorsque ce dernier le demande via le cron, les fichiers à sauvegarder ;
- Le répertoire /srv/rsync du serveur contient un répertoire par utilisateur du service et ce répertoire stocke X sauvegardes. Chaque sauvegarde est exploitable si l'on veut récupérer des données dedans (par simple copier coller si vous partagez les répertoires sur le réseau). Une sauvegarde sera nommée par sa date et il sera possible de récupérer un fichier donné dans une sauvegarde en particulier même si le fichier a depuis été sauvegardé quelques fois dans une version changée.
Aperçu de l'arborescence des sauvegardes
/srv/rsync +---o user1 +---o 20100413-070000 +---o 20100413-130000 +---o 20100415-070000 +---o current -> 20100415-070000 +---o user2 +---o 20100413-070000 +---o 20100413-130000 +---o 20100415-070000 +---o current -> 20100415-070000
Le fichier current sera un lien (symbolique cette fois-ci) pointant vers la dernière sauvegarde. Il sera utilisé par le script de sauvegarde pour déterminer à partir de quelle sauvegarde il devra lier en dur la nouvelle.
Accueil des sauvegardes clientes
La destination de ces sauvegardes sera /srv/rsync. Il faut donc s'assurer, si ce n'est pas le cas, que l'arborescence suivante existe bien (le propriétaire est le root) :
# mkdir -p /srv/rsync/{user1,user2,user3}
Installation de rsync sur le serveur
L'installation de rsync sera effective après que le paquet suivant soit demandé à aptitude :
# aptitude install -y rsync
Sauvegardes automatisées depuis le cron du serveur
La sauvegarde doit avoir lieu à des moments de la journée où les machines sont susceptibles d'être allumées, il faut inscrire des appels à la commande de sauvegarde dans le cron de l'utilisateur root du serveur.
# crontab -e 15 7 * * * /srv/scripts/rsync.sh 0 13 * * * /srv/scripts/rsync.sh 0 21 * * * /srv/scripts/rsync.sh
Il faut veiller à installer le client rsync sur chacun des postes clients de cette façon :
# aptitude install -y rsync openssh-server
Notes :
- Il est important de demander l'installation du serveur SSH sur les clients, il est suggéré par le paquet rsync mais pas installé par défaut. C'est le protocole de transport par défaut pour toute session rsync.
- Pour éviter que la demande de sauvegarde ne demande un mot de passe, il faut définir le serveur comme un client SSH de confiance. Pour cela, on créé un couple de clefs publique et privée dont le mot de passe est blanc. Il faut terminer en ajoutant cette toute récente clef publique sur chacun des clients.
# ssh-keygen -t rsa # ssh-copy-id -i /root/.ssh/id_rsa.pub user1@laptop-1 # ssh-copy-id -i /root/.ssh/id_rsa.pub user2@laptop-2 # ssh-copy-id -i /root/.ssh/id_rsa.pub user3@desktop-3
Suite à cet ajout des clefs sur les clients, il pourrait être bon de désactiver la connexion par simple mot de passe sur ces derniers. Je vous laisse faire les recherches qui s'imposent si ce sujet vous est étranger.
Script de sauvegarde
Le paragraphe précédent montre l'appel à différents moments de la journée au script rsync.sh que voici :
# vi /srv/scripts/rsync.sh
##============================================================================ ## Fichier : rsync.sh ## Auteur : Phil ## Licence : GNU GPL v3 - http://www.gnu.org/licenses/gpl.html ## Description : Script de sauvegarde via Rsync ##============================================================================ ## Parametres d'entree : liste des profils a sauvegarder. ## Exemple d'appel : rsync.sh phil nath ## Code de retour : ## 0 - La sauvegarde rsync s'est correctement terminee. ##============================================================================ ##################################### # GESTION DE L'APPEL DE LA COMMANDE # ##################################### # Recuperation des profils passes en parametre. if [ $# -ne 0 ] then while [ $# -ne 0 ] do users+="$1 " shift done # Aucun profil n'est passe en parametre, on fait donc la sauvegarde pour tout # le monde. else users="user1 user2 user3" fi #################################### # BOUCLE DE SAUVEGARDE DES PROFILS # #################################### for utilisateur in $users do ####################################################### # PREPARATION DE LA SAUVEGARDE ET GESTION DES PROFILS # ####################################################### date_sauvegarde=$(date "+%Y%m%d_%H%M%S") # Creation d'un fichier temporaire pour y ecrire les fichiers et # repertoires a ne pas sauvegarder (pour ne mettre que le fichier # temporaire en parametre de la commande rsync) ce_quil_ne_faut_pas_sauvegarder=$(tempfile) :>$ce_quil_ne_faut_pas_sauvegarder # Exclusions generales echo "*~" >> $ce_quil_ne_faut_pas_sauvegarder echo echo "${date_sauvegarde} - Sauvegarde du profil utilisateur ${utilisateur}" echo "-------------------------------------------------------" case "${utilisateur}" in "user1") poste="laptop-1" port=22 nombre_de_sauvegardes=100 ce_quil_faut_sauvegarder="/home/user1/" # Exclusions particulieres echo "temp/" >> $ce_quil_ne_faut_pas_sauvegarder ;; "user2") poste="laptop-2" port=22 nombre_de_sauvegardes=50 ce_quil_faut_sauvegarder="/home/user2/" ;; "user3") poste="desktop-3" port=443 nombre_de_sauvegardes=50 ce_quil_faut_sauvegarder="/home/user3/" ;; *) echo "L'utilisateur n'est pas reconnu." >&2 erreur_profil_inconnu=1 ;; esac # Si le profil en cours de sauvegarde n'existe pas, on passe au suivant. if [[ ${erreur_profil_inconnu} -eq 1 ]] then erreur_profil_inconnu=0 continue; fi # Si le repertoire de sauvegarde n'existe pas, je le cree. if [ ! -d /srv/rsync/"${utilisateur}" ] then echo "L'emplacement de la sauvegarde n'existait pas." mkdir /srv/rsync/"${utilisateur}" fi ############## # SAUVEGARDE # ############## if [[ -L /srv/rsync/"${utilisateur}"/current \ && -d /srv/rsync/"${utilisateur}"/current ]] then # Si une precedente sauvegarde existe, on la lie en dur. rsync --delete-before --delete-excluded --partial \ --skip-compress=gz/jpg/mp[34]/7z/bz2 --stats -rlpthz \ --link-dest=/srv/rsync/"${utilisateur}"/current \ --exclude-from "${ce_quil_ne_faut_pas_sauvegarder}" \ -e "ssh -p ${port}" \ "${utilisateur}"@"${poste}":"${ce_quil_faut_sauvegarder}" \ /srv/rsync/"${utilisateur}"/"${date_sauvegarde}"/ else # Sinon, on en cree une toute neuve ! rsync --exclude='*~' --delete-before --delete-excluded --partial \ --skip-compress=gz/jpg/mp[34]/7z/bz2 --stats -rlpthz \ -e "ssh -p ${port}" \ "${utilisateur}"@"${poste}":"${ce_quil_faut_sauvegarder}" \ /srv/rsync/"${utilisateur}"/"${date_sauvegarde}"/ fi retour_rsync=$? echo # Pour passer une ligne :) # Suppression du fichier temporaire qui stocke les repertoires a exclure rm $ce_quil_ne_faut_pas_sauvegarder ####################### # GESTION DES ERREURS # ####################### # Pas d'erreur if [ $retour_rsync == 0 ] then # La sauvegarde a reussit, on cree un lien "current" pour retenir la # derniere. rm -f /srv/rsync/"${utilisateur}"/current 2>/dev/null ln -s /srv/rsync/"${utilisateur}"/"${date_sauvegarde}"/ \ /srv/rsync/"${utilisateur}"/current # Si le nombre de snapshots depasse nombre_de_sauvegardes, je purge. nombre_snapshots=$((`ls /srv/rsync/"${utilisateur}" | wc -l` - 1)) if [ ${nombre_snapshots} -gt $nombre_de_sauvegardes ] then # On supprime la plus vieille des sauvegardes plus_ancienne="$(ls /srv/rsync/"${utilisateur}" | head -n 1)" rm -rf /srv/rsync/"${utilisateur}"/"${plus_ancienne}" echo "Purge de la plus ancienne sauvegarde : ${plus_ancienne}." else echo "Aucune sauvegarde anterieure ne doit etre supprimee." fi # Probleme lors de la sauvegarde rsync else # La sauvegarde a echouee, on affiche une erreur et on supprime la # tentative. echo "La commande rsync a echouee pour l'utilisateur ${utilisateur}." echo "Suppression de la sauvegarde en erreur : ${date_sauvegarde}." rm -rf /srv/rsync/"${utilisateur}"/"${date_sauvegarde}"/ fi done exit 0
Pensez à rendre ce script exécutable par son propriétaire (root chez moi) :
# chmod u+x /srv/scripts/rsync.sh
Notes et références
Ce chapitre n'est qu'une simple implémentation de ce qui est décrit dans l'excellent article http://www.sanitarium.net/golug/rsync_backups_2010.html (ce dernier décrit très précisément la notion de liens durs, je vous invite donc à le lire ; par contre, il lui manquait la description de la mise en place d'un tel service, script inclu).
- Vous êtes libres d'améliorer cette page qui comporte probablement ses défauts. Le script est certainement perfectible aussi.