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-070000Le 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.shIl 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 0Pensez à 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.
