Backup linux

La semaine dernière en cherchant à recréer mon bootloader j’ai perdu une partition qui contenait des données importantes. Il était temps que je mette enfin en place un système de sauvegarde de mes données ! Cette page décrit le système que j’ai mis en place pour que vous puissiez facilement le reproduire et ne plus perdre vos données !

Le mécanisme décrit ici fonctionne sur n’importe quelle distribution Linux puisque le seul programme nécessaire est rsync en version 2.5.6 ou supérieure. Il s’appuie sur les scripts de Mike Rubel dont la page très détaillée est ici.

Le résultat

J’ai un disque dédié au backup. Le jour où le disque principal lâche ça ne sert pas à grand-chose si la sauvegarde est sur le même disque. Ce disque de backup contient une seule partition au format ext4, avec un répertoire snapshot à l’intérieur duquel j’ai les répertoires suivants :

Je conserve 7 daily, 5 weekly, et 7 monthly. Chacun de ces snapshots contient l’arborescence que j’ai choisi de sauvegarder :

/snapshot/
+- daily.0/
|  +- boot/
|  +- etc/
|  +- home/
|  +- root/
|  +- usr/
|  +- var/
+- daily.1
|  +- ...
+- ...

La magie du mécanisme utilisé est que ces 19 sauvegardes ne prennent au total qu’environ 2 fois le volume sauvegardé.

Comment ça marche ?

Avec les systèmes de fichiers ext2, ext3 ou ext4, un fichier est une étiquette (par exemple /etc/group ou /tmp/a) qui pointe vers un espace de stockage sur le disque appelé inode, où sont écrites les données ainsi que les dates et permissions. Vous pouvez voir le numéro d’inode d’un fichier à l’aide de la commande ls -i :

% touch /tmp/a
% ls -i /tmp/a
3385746 /tmp/a

Lorsque vous effacez un fichier, Linux supprime l’étiquette et, si aucune autre étiquette ne pointe vers le même inode, le libère. Aucune autre étiquette ?! Eh oui, il est possible d’avoir plusieurs étiquettes qui pointent sur le même inode. Pour savoir combien, stat /tmp/a

Pour créer une 2nde étiquette on crée un lien physique (à ne pas confondre avec les liens symboliques créés par ln -s) avec la commande ln :

% ln /tmp/a /tmp/b
% ls -i /tmp/a /tmp/b
3385746 /tmp/a
3385746 /tmp/b
% rm /tmp/b

C’est un peu comme la commande cp, sauf que celle-ci alloue un nouvel inode (avec de nouvelles permissions) :

% cp /tmp/a /tmp/b
% ls -i /tmp/a /tmp/b
3385746 /tmp/a
2812276 /tmp/b
% rm /tmp/b

La commande cp -l crée des liens physiques, et cp -a copie toute une arborescence en préservant les dates et les permissions. cp -al permet de dupliquer toute une arborescence avec des liens physiques ! On a ainsi l’impression d’avoir une copie complète de l’arborescence alors que cela n’occupe presque aucun espace disque.

Pour notre système de sauvegarde on ne souhaite pas faire de liens physiques (c’est de toute façon impossible entre deux disques), en revanche entre nos différents snapshots ça va nous permettre de gagner beaucoup de place.

rsync

rsync est un utilitaire en ligne de commande très pratique pour recopier une arborescence. rsync -a fait la même chose que cp -a, sauf que si l’arborescence cible existe déjà rsync ne copiera que les fichiers qui ont changé, ce qui va beaucoup plus vite. Et avec l’option --delete, il effacera de la cible les fichiers qui ont disparu de la source.

Attention, si src est un répertoire, rsync -a src dst créera un répertoire src sous dst/, alors que rsync -a src/ dst (avec un slash) copiera directement le contenu de src sous dst/. En revanche, un slash ou non à la fin de dst ne change rien.

Enfin rsync possède depuis la version 2.5.6 une option --link-dest qui duplique l’arborescence cible avec des liens physiques et met à jour uniquement cette copie :

rsync -a --delete --link-dest=../dest.old source/ dest.new

Le script

Avec tout ça, le principe de notre script de backup est simple :

Télécharger le script : snapshot.sh (4 Ko)

Configuration

Vous pouvez changer le nombre de snapshots conservés au début du script (DAILY_MAX etc.), et l’emplacement de votre répertoire de backup (SNAPSHOT_RW).

Il faut surtout configurer les répertoires sauvegardés en modifiant la variable TOBACKUP. Attention si vous mettez dans TOBACKUP le répertoire /home/toto, alors le répertoire créé sous daily.0 sera daily.0/toto et pas daily.0/home/toto. Pour cela, mettez /home dans TOBACKUP et éditez ensuite le fichier snapshot_exclude.txt.

Le format de ce fichier est le suivant : un ‘-’ (ou rien) signifie une exclusion, un ‘+’ signifie une inclusion. Pour savoir si un fichier doit être copié, rsync prend les lignes une par une et prend le statut de la 1ère ligne qui matche. Si aucune ligne ne matche le fichier est copié. dir/* matche les fichiers/répertoires situés directement sous dir/, alors que dir/** matche tout ce qui est situé à une profondeur quelconque. Attention si l’on exclut dir/** et que l’on veut inclure dir/a/b/* il faut explicitement inclure dir/a et dir/b en plus de dir/a/b/*.

À titre d’exemple voici mon fichier : snapshot_exclude.txt (4 Ko)

Lancement automatique

Placez le script et le fichier d’exclusions dans le même répertoire (par exemple /root) et vérifiez que le script a les droits d’exécution (chmod 755 snapshot.sh). Pour vérifier le bon fonctionnement, lancez /root/snapshot.sh daily

Si ça fonctionne, automatisez le lancement en mettant dans /etc/crontab :

# Snapshot chaque jour à 2h, et chaque lundi/1er à 15h 12/28
1 2     * * *   root    /root/scripts/snapshot.sh daily
12 15   * * 1   root    /root/scripts/snapshot.sh weekly
28 15   1 * *   root    /root/scripts/snapshot.sh monthly

Pour sauvegarder sous Ubuntu (ou Debian) la liste des paquets installés, ajoutez la commande suivante pour qu’elle se lance avant le daily :

0 2     * * *   root    dpkg --get-selections >| /root/get-selections.txt
Cet article publié en août 2010 a été mis à jour.

En lire plus sur : linux