Publié le 14 avril 2023
C’est peu connu, mais rsync permets de faire des sauvegardes
incrémentales plutôt efficaces. L’option --link-dest
permets de garder plusieurs version d’une même arborescence, mais en
créant des liens en dur (hardlink) entre les fichiers qui n’ont pas
changé.
Pour l’exemple, je créé un dossier www
avec trois
fichiers :
ls -hl www/
total 12K
-rw-r--r-- 1 root root 4 Apr 14 10:25 fichier1.txt
-rw-r--r-- 1 root root 4 Apr 14 10:25 fichier2.txt
-rw-r--r-- 1 root root 5 Apr 14 10:25 fichier3.txt
Si je veux en faire une sauvegarde avec rsync
, je vais
faire :
rsync -arv www/ sauvegarde1/
sending incremental file list
created directory sauvegarde
./
fichier1.txt
fichier2.txt
fichier3.txt
sent 272 bytes received 109 bytes 762.00 bytes/sec
total size is 13 speedup is 0.03
Et dans mon dossier sauvegarde1
, j’ai bien :
ls -hl sauvegarde1/
total 12K
-rw-r--r-- 1 root root 4 Apr 14 10:25 fichier1.txt
-rw-r--r-- 1 root root 4 Apr 14 10:25 fichier2.txt
-rw-r--r-- 1 root root 5 Apr 14 10:25 fichier3.txt
Maintenant dans www
, je vais modifier
fichier1.txt
, supprimer fichier3.txt
et créer
fichier4.txt
:
ls -hl www/
total 8.0K
-rw-r--r-- 1 root root 11 Apr 14 10:29 fichier1.txt
-rw-r--r-- 1 root root 4 Apr 14 10:25 fichier2.txt
-rw-r--r-- 1 root root 7 Apr 14 10:30 fichier4.txt
Je fais une nouvelle sauvegarde dans sauvegarde2
:
rsync -arv www/ sauvegarde2/
sending incremental file list
created directory sauvegarde2
./
fichier1.txt
fichier2.txt
fichier4.txt
sent 279 bytes received 110 bytes 778.00 bytes/sec
total size is 22 speedup is 0.06
Je retrouve le contenu attendu dans sauvegarde2
:
ls -hl sauvegarde2/
total 12K
-rw-r--r-- 1 root root 11 Apr 14 10:29 fichier1.txt
-rw-r--r-- 1 root root 4 Apr 14 10:25 fichier2.txt
-rw-r--r-- 1 root root 7 Apr 14 10:30 fichier4.txt
Ici je me retrouve avec trois dossier : la source dans
www
, et deux sauvegardes dans sauvegarde1
et
sauvegarde2
. C’est ce qui est attendu, mais ce n’est pas
optimal. Plusieurs fichiers sont présents plusieurs fois :
fichier2.txt
est dans www
,
sauvegadre1
et sauvegarde2
fichier4.txt
est dans www
et
sauvegarde2
fichier1.txt
est dans www
,
sauvegadre1
et sauvegarde2
, mais il a changé
entre sauvegarde1
et sauvegarde2
On voit ici qu’il y a plusieurs doublons, et qu’il y a moyen de gagner de la place. On pourrait ne pas re-sauvegarder les fichiers qui n’ont pas changé. Mais pour des facilités d’utilisation j’aimerais bien que tous les fichiers soient présents dans tous les répertoires. Ça pourrait me permettre de récupérer rapidement un dossier complet en cas de besoin.
Sous Linux, il y a deux façons de faire des liens :
Les liens symboliques : c’est les raccourci. Un petit fichier contient l’endroit auquel le système d’exploitation doit aller chercher le vrai fichier. Ça permets de faire des liens vers tout et n’importe quoi : fichier sur le disque, fichier réseau,… Par contre si la cible disparaît, le lien symbolique est toujours là mais ne pointe plus vers rien.
Les liens en durs (hardlink) : cette fois-ci le fichier est présent physiquement à deux endroits de la partition (pour faire technique, le fichier a plusieurs entrées dans la table des inodes). Si le fichier est supprimé à un emplacement, il est toujours disponible au deuxième. Et toute modification se répercute des deux côtés. L’inconvénient c’est que les liens en dur ne peuvent se faire que sur le même système de fichiers.
Comme dit plus haut, rsync
permets de gérer nativement
plusieurs version d’un même dossier grâce aux liens en dur. Je vais
reprendre mon exemple précédent.
Je repart sur les trois fichiers de base :
ls -hl www/
total 12K
-rw-r--r-- 1 root root 4 Apr 14 10:51 fichier1.txt
-rw-r--r-- 1 root root 4 Apr 14 10:51 fichier2.txt
-rw-r--r-- 1 root root 5 Apr 14 10:51 fichier3.txt
Maintenant je fais une première sauvegarde, comme la fois précédente :
rsync -arv www/ sauvegarde1/
sending incremental file list
created directory sauvegarde1
./
fichier1.txt
fichier2.txt
fichier3.txt
sent 271 bytes received 110 bytes 762.00 bytes/sec
total size is 13 speedup is 0.03
Dans www
je modifie fichier1.txt
, je
supprimer fichier3.txt
et je créer
fichier4.txt
:
ls -hl www/
total 12K
-rw-r--r-- 1 root root 11 Apr 14 10:53 fichier1.txt
-rw-r--r-- 1 root root 4 Apr 14 10:51 fichier2.txt
-rw-r--r-- 1 root root 7 Apr 14 10:54 fichier4.txt
Maintenant, pour la deuxième sauvegarde, je vais utiliser l’option
--link-dest
de rsync
:
rsync -arv --link-dest /root/test_rsync/sauvegarde1/ www/ sauvegarde2/
sending incremental file list
created directory sauvegarde2
./
fichier1.txt
fichier4.txt
sent 236 bytes received 92 bytes 656.00 bytes/sec
total size is 22 speedup is 0.07
Notez que l’option --link-dest
demande absolument un
chemin absolu (depuis la racine).
D’après ce qui est affiché, seuls fichier1.txt
et
fichier4.txt
ont été sauvegardés. Mais si je regarde le
contenu du répertoire, fichier2.txt
est bien présent :
ls -hl sauvegarde2
total 12K
-rw-r--r-- 1 root root 11 Apr 14 10:53 fichier1.txt
-rw-r--r-- 2 root root 4 Apr 14 10:51 fichier2.txt
-rw-r--r-- 1 root root 7 Apr 14 10:54 fichier4.txt
Notez le 2
juste après le -rw-r--r--
. Ça
veut dire que ce fichier possède deux entrées dans la table des inodes.
rsync
a détecté que le fichier était identique entre
sauvegarde1
et sauvegarde2
et ne l’a pas
re-créé, il s’est contenté de faire un lien en dur. Par contre il a
détecté que fichier1.txt
avait été modifié, et l’a créé
dans sauvegarde2
. Et pareil pour fichier4.txt
qui était nouveau.
Sur cet exemple ça ne casse pas des briques, mais sur une grosse sauvegarde ça permets d’économiser beaucoup de place (et beaucoup de bande passante si on passe par le réseau). Et ça marche avec plus de deux sauvegardes.
Il faut quand même faire attention à plusieurs points :
Toutes les sauvegardes doivent être sur le même système de
fichiers. Ce n’est pas nécessaire pour la source
(www
).
La sauvegarde est incrémentale, mais simplement au niveau fichier. S’il y a un seul octet d’écart entre un fichier source et sa sauvegarde, tout le fichier est ré-écrit.
L’option --link-dest
est sensible aux droits. Si un
fichier source et sa sauvegarde ont exactement le même contenu mais des
droits différents, il sera ré-écrit.
Si un lien en dur est modifié d’un côté, il l’est aussi de
l’autre. Dans l’exemple ci-dessus, toute modification de
sauvegarde1/fichier2.txt
sera répercutée dans
sauveagdre2/fichier2.txt
. Il ne faut donc
jamais modifier un fichier dans un répertoire de
sauvegarde.
Corollaire : il ne faut pas utiliser l’option
--link-dest
entre le fichier d’origine (www
)
et la première sauvegarde. Sinon rsync ne va faire que des liens en dur
et toute modification de la source modifiera la sauvegarde.
Je dispose d’un NAS sur lequel je fais toutes mes sauvegardes. Il y a dessus un répertoire par équipement à sauvegarde, à l’intérieur duquel il y a un répertoire par date. Par exemple, pour les sauvegardes du serveur qui héberge ce site, ça donne ça :
palc@nas:/data/Sauvegardes$ ls -hl palc.fr/
total 0
drwxr-xr-x 1 palc palc 1,5K 31 août 2022 2022-08-31
drwxr-xr-x 1 palc palc 1,5K 15 déc. 08:12 2022-12-14
drwxr-xr-x 1 palc palc 1,4K 16 févr. 22:31 2023-02-16
drwxr-xr-x 1 palc palc 1,4K 9 mars 12:02 2023-03-09
Et voici l’espace occupé par les différentes sauvegardes :
pacl@nas:/data/Sauvegardes$ du -csh palc.fr/*
94G palc.fr/2022-08-31
19G palc.fr/2022-12-14
7,6G palc.fr/2023-02-16
13G palc.fr/2023-03-09
132G total
On voit bien que les les trois dernières sauvegardes sont beaucoup plus petites que la première, grâce à l’utilisation des liens en dur.
Maintenant voyons comment je procède pour mes sauvegardes.
La première sauvegarde se fait de manière traditionnelle :
rsync -avzz --delete --exclude="/bin/" --exclude="/boot/" --exclude="/dev/" --exclude="/lib/" --exclude="/mnt/" --exclude="/proc/" --exclude="/run/" --exclude="/sbin/" --exclude="/sys/" --exclude="/tmp/" --exclude="/usr/" --exclude="/var/cache/" --exclude="/var/lib/" --exclude="/var/log/" --exclude="/var/tmp/" palc.fr:/ /data/Sauvegardes/palc.fr/2022-08-31/
On notera que je préfère faire des exclude
des
répertoire inutiles plutôt qu’un include
des répertoires
utiles. C’est pour éviter d’oublier un répertoire important.
Les sauvegardes suivantes se font avec cette commande :
rsync -avzz --exclude="/bin/" --exclude="/boot/" --exclude="/dev/" --exclude="/lib/" --exclude="/mnt/" --exclude="/proc/" --exclude="/run/" --exclude="/sbin/" --exclude="/sys/" --exclude="/tmp/" --exclude="/usr/" --exclude="/var/cache/" --exclude="/var/lib/" --exclude="/var/log/" --exclude="/var/tmp/" --link-dest /data/Sauvegardes/palc.fr/`ls -1 /data/Sauvegardes/palc.fr/ | grep -v $(date +%Y-%m-%d) | tail -n 1`/ palc.fr:/ /data/Sauvegardes/palc.fr/`date +%Y-%m-%d`/
Vous noterez l’utilisation de date +%Y-%m-%d
. Ça me
permets de définir automatiquement la destination de la sauvegarde dans
le dossier du jour.
Le
ls -1 /data/Sauvegardes/palc.fr/ | grep -v $(date +%Y-%m-%d) | tail -n 1
,
utilisé pour l’option --link-dest
, permets de trouver le
dernier dossier de sauvegarde, en excluant celui du jour. De cette
façon, si une sauvegarde a été interrompue en plein milieu, il est
possible de relancer la commande, telle quelle.
Il y a deux points sur lesquels il faut faire attention :
rsync
.