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 :
- daily.0 : la copie du matin
- daily.1 : celle de la veille
- daily.2 etc. : celle des jours précédents
- weekly.0 : celle du lundi précédent
- weekly.1 etc. : celle des semaines précédentes
- monthly.0 etc. : celle du 1er du mois et des mois précédents
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 :
- On lance
rsync
en lui demandant de dupliquerdaily.0
endaily
et de modifierdaily
; - On fait tourner les backups (on supprime
daily.6
, on renommedaily.5
endaily.6
et ainsi de suite jusqu’àdaily
endaily.0
) ; - Chaque lundi on fait un
cp -al
dedaily.0
versweekly
, et chaque 1er du mois dedaily.0
versmonthly
. Et l’on fait tourner les backups.
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.