comment obtenir rsync pour lier des fichiers identiques avec l'option --link-dest si un ancien fichier existe déjà?

11

On pourrait penser --link-destqu'utiliser un fichier identique fonctionnerait dans tous les cas. Mais ce n'est pas le cas lorsque le fichier existe, même si le fichier est obsolète / a un contenu différent.

C'est à cause de cela, à partir de la page de manuel rsync sur --link-dest:

"Cette option fonctionne mieux lors de la copie dans une hiérarchie de destination vide, car rsync traite les fichiers existants comme définitifs (donc rsync ne regarde jamais dans les répertoires de destination de lien quand un fichier de destination existe déjà )"

Cela signifie que s'il y/fileexiste identique à la source et z/fileest obsolète,

rsync -a --del -link-dest=y source:/file z

entraînera l'utilisation de DEUX inodes (et deux fois l'espace disque) y/fileet z/file, qui auront le même contenu et les mêmes horodatages.

Je suis tombé sur cela parce que je fais des sauvegardes quotidiennes essentiellement avec ce script exécuté une fois par jour:

mv $somedaysago $today; 
yest=$today; today=`date +%Y%m%d`;
rsync -avPShyH --del --link-dest=../$yest host:/dirs $today

Parce que mes sauvegardes s'étendent jusqu'à 10 millions de fichiers, cela rm -rf $olddir; rsync source:$dir newdirprendrait beaucoup trop de temps (surtout lorsque seulement 0,5% des fichiers changent par jour, entraînant la suppression et la création d'entrées de 10 millions de dir juste pour gérer 50 000 fichiers nouveaux ou modifiés, ce qui rendrait mon sauvegardes incomplètes à temps pour le lendemain).

Voici une démo de la situation:

aest notre source, à 1travers 4nos sauvegardes numérotées:

$ mkdir -p 1 2; echo foo > 1/foobar; cp -lrv 1/* 2
`1/foobar' -> `2/foobar'
$ ls -i1 */foobar
1053003 1/foobar
1053003 2/foobar

$ mkdir a; echo quux > a/foobar
$ mv 1 3; rsync -avPhyH --del --link-dest=../2 a/ 3
sending incremental file list
./
foobar
           5 100%    0.00kB/s    0:00:00 (xfer#1, to-check=0/2)

sent 105 bytes  received 34 bytes  278.00 bytes/sec
total size is 5  speedup is 0.04

$ ls -i1 */foobar
1053003 2/foobar
1053007 3/foobar
1053006 a/foobar

$ mv 2 4; rsync -avPhyH --del --link-dest=../3 a/ 4
sending incremental file list
./
foobar
           5 100%    0.00kB/s    0:00:00 (xfer#1, to-check=0/2)

sent 105 bytes  received 34 bytes  278.00 bytes/sec
total size is 5  speedup is 0.04


$ ls -il1 */foobar
1053007 -rw-r--r-- 1 math math 5 Mar 30 00:57 3/foobar
1053008 -rw-r--r-- 1 math math 5 Mar 30 00:57 4/foobar
1053006 -rw-r--r-- 1 math math 5 Mar 30 00:57 a/foobar

$ md5sum [34a]/foobar
d3b07a382ec010c01889250fce66fb13  3/foobar
d3b07a382ec010c01889250fce66fb13  4/foobar
d3b07a382ec010c01889250fce66fb13  a/foobar

Nous avons maintenant 2 sauvegardes a/foobaridentiques à tous égards, y compris l'horodatage, mais occupant des inodes différents.

On pourrait penser qu'une solution serait --delete-before, ce qui tue l'avantage de l'analyse incrémentielle, mais cela n'aide pas non plus car le fichier ne sera pas supprimé, mais utilisé comme base dans le cas où une copie incrémentielle est possible.

On pourrait supposer davantage que nous pouvons désactiver cette couverture de copie incrémentielle avec --whole-file, mais cela n'aide pas l'algorithme, il n'y a aucun moyen d'obtenir ce que nous voulons.

Je considère ce comportement comme un autre bogue dans rsync, où un comportement bénéfique pourrait être interprété à partir de sélections soigneuses de divers arguments de commande, mais le résultat souhaité n'est pas disponible.

Une solution consisterait malheureusement à passer d'un seul rsync en tant qu'opération atomique à une exécution à sec avec -n, à le journaliser, à traiter ce journal en entrée pour pré-supprimer manuellement tous les fichiers modifiés, puis à exécuter rsync --link-destpour obtenir ce que nous voulons - un gros coup de pouce par rapport à un seul rsync propre.

Addendum: a essayé de pré-lier $yesterdayet $todaysur le serveur de sauvegarde avant la sauvegarde contre les boîtes de production avec rsync --link-dest=../$yesterday $yesterday/ $today- mais le même résultat - tout fichier qui existe de quelque manière que ce soit, même la longueur 0, ne sera jamais supprimé et destiné au lien, au lieu d'un tout une nouvelle copie sera faite à partir du sourcedir avec un nouvel inode et utilisant plus d'espace disque.

Envisager pax(1)comme une solution possible de pré-liaison avant la sauvegarde.

math
la source
J'utilise --delete-afterdans ce scénario d'utilisation, quel est le problème avec cela?
gogoud
1
--delete-afterest très bien, mais sans rapport avec le problème en question. Les fichiers manquants dans la source seront supprimés une fois la copie terminée. Le problème que j'élucide concerne une sauvegarde effectuée aujourd'hui qui est identique à celle d'hier mais contre un ancien fichier obsolète existant qui n'est pas lié à l'inode d'hier, mais stocké en tant que nouveau fichier à deux fois l'espace disque total lorsque celui d'hier une copie identique est considérée.
math
Je ne sais pas exactement ce que vous remettez en question. Avez-vous réfléchi rsnapshot? Pensez également à écrire un petit script pour relier des fichiers "identiques". Je fais les deux sur mes systèmes.
roaima
1
Si vous n'obtenez pas la réponse dont vous avez besoin ici, vous pouvez publier sur la liste rsync. Les développeurs de rsync y répondent régulièrement avec de nombreux utilisateurs avancés. Vous pouvez les trouver via lists.samba.org/mailman/listinfo/rsync . Je me cache surtout là-bas et j'apprends beaucoup.
Joe
rsnapshot ne recyclera pas les anciennes sauvegardes - et je dois le faire: si j'ai des sauvegardes de 2 mois et 2 mois + 1 jour, je peux en faire un en tant que nouvelle cible. Puisque ~ 5% des fichiers changent / jour, je crée des liens durs de 50K au lieu de 10M. Cette différence de vitesse permet de sauvegarder 5 serveurs / nuit vs non. hardlink(1)est lent (15 fois plus lent que l'analyse des métadonnées de rsync); paxest plus rapide mais écrase les têtes de disque dur en comparant l'ancienne sauvegarde à la nouvelle. rsync -npour obtenir la liste delta, il faut frapper deux fois les serveurs de production (l'analyse de 10 millions de fichiers a bien plus d'impact que la copie des modifications de 50 Ko). Ill envoyer la liste d'une option dans rsync pour autoriser cela.
math

Réponses:

12

(Converti de l'édition de questions)

Ceci est résolu par la mise à niveau de rsync. La version 3.1.1 ou ultérieure remplacera désormais les fichiers identiques dans la cible et le --link-destrépertoire par un fichier lié en dur. Économise beaucoup d'espace.

Michael Mrozek
la source