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" :

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 :

# 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



CategoryFrCategory CategoryFrCategory