Wie kann ich mit rsync einen Verzeichnisbaum duplizieren und Hardlinks zu Dateien erstellen?

23

Von Zeit zu Zeit muss ich mehrere große Migrationsänderungen an Datendateien auf meinem Server vornehmen, und ich suche nach einer guten Möglichkeit, dies zu tun. Ich habe darüber nachgedacht, meine Verzeichnisstruktur mit rsync zu duplizieren, beginnend mit dem Stammdatenordner, und feste Links zu allen Originaldateien zu erstellen (einige davon sind ziemlich groß). Außerdem kann ich im Zielbaum nur die Dateien überschreiben, die migriert werden müssen. Am Ende kann ich mit zwei mvOperationen sicher von den alten Dateien auf die neuen Dateien wechseln .

Es scheint jedoch nicht möglich zu sein, Rsync dazu zu bringen. Ich habe es versucht

rsync -a --link-dest=$DATA $DATA $DATA/../upgrade_tmp

Anstatt feste Verknüpfungen zu Dateien zu erstellen, kopiert rsync diese vollständig. Gibt es ein Problem mit demselben Quell- und Linkzielverzeichnis?

Jean-Philippe Pellet
quelle

Antworten:

21

rsync ist ein mächtiges Werkzeug, aber es ist leider seltsam wählerisch in Bezug auf einige seiner Pfadnamen.

Wenn $DATAes sich um einen absoluten Pfad handelt (dh er beginnt mit einem /), lautet die zu verwendende Befehlszeile wie folgt:

rsync -a --link-dest=$DATA $DATA/ $DATA/../upgrade_tmp

[Nun, nur eine kurze Seite über rsyncdie Seltsamkeit. Beachten Sie das zum Quellargument /hinzugefügte Trailing . Dies bedeutet, dass rsyncmit dem Inhalt des Quellverzeichnisses und nicht mit dem Quellverzeichnis selbst gearbeitet werden soll. (Ich gehe davon aus, dass $DATAdas nicht bereits ein Trailing enthält /.) In diesem Fall möchten wir mit dem Inhalt arbeiten, also fügen wir das Trailing hinzu /.]

Wenn auf der anderen Seite $DATAist ein relativer Pfad (dh es beginnt nicht mit ein /), dann Kommentar Sean R etwa --link-destist Knall auf: Der Link-dest Pfad wird relativ zu dem interpretierten Zielpfad, so dass Sie die folgenden Befehle verwenden:

rsync -a --link-dest=../`basename $DATA` $DATA/ $DATA/../upgrade_tmp

BEARBEITEN

Eine letzte Anmerkung: Es stellt sich heraus, dass die zweite rsyncBefehlszeile, die ich gegeben habe, funktionieren sollte, unabhängig davon, ob $DATAes sich um einen absoluten Pfad handelt, da basenamees egal ist, ob ein Pfad absolut oder relativ ist.

Steven Montag
quelle
1
Nur ein fehlender Schrägstrich, wer hätte das gedacht ... Danke für die nette Erklärung!
Jean-Philippe Pellet,
Vielen Dank dafür, ich habe versucht, mehrere inkrementelle Sicherungsanweisungen wie diese zu befolgen, und habe keine Erwähnung dieser Eigenart gefunden. Dies war das einzige, was tatsächlich dafür sorgte, dass Dateien fest verbunden wurden. Vergewissern Sie sich, dass die Ref-Anzahl> 1 war und die Inode-Nummern mitls -ilah
Walf
Ich habe dies in Verbindung mit der relpath () -Funktion verwendet, die unter unix.stackexchange.com/a/85068/57414 beschrieben ist, um ein $SOURCEVerzeichnis in ein Verzeichnis $TARGETwie das folgende zu sichern :SOURCE='abs_path_to_backup'; TARGET='.'; rsync -a --link-dest=$(relpath $TARGET $SOURCE) $SOURCE/ $TARGET/
Nathan S. Watson-Haigh
13

Was Sie wollen, ist "cp -al":

cp -al $DATA/ $DATA/../upgrade_tmp/
  • -a rekursiv wie rsync -a
  • -l wird Dateien fest verlinken, anstatt sie zu kopieren.
Sean Reifschneider
quelle
1
cp -alist auf meinem System leider nicht verfügbar (Mac OS X 10.6). Ich werde stattdessen Pax verwenden ...
Jean-Philippe Pellet
7

Die --link-destOption in rsyncist relativ zum Zielverzeichnis und nicht zum aktuellen Verzeichnis. Also, was Sie wollen, ist:

rsync -a --link-dest=../`basename $DATA` $DATA $DATA/../upgrade_tmp
Sean Reifschneider
quelle
Ups, ich meinte basename, ursprünglich hatte ich dirname.
Sean Reifschneider
1
Die Manpage besagt, dass diese --link-destOption, wenn sie relativ ist, relativ zum Zielverzeichnis ist. In meinem Fall ist es absolut. Selbst wenn es relativ zum Zielverzeichnis erstellt wird, funktioniert dies nicht.
Jean-Philippe Pellet,
7

Es stellt sich heraus, dass dies schwieriger ist rsyncals mit anderen Werkzeugen. Die richtige Antwort rsynclautet Steven Monais, aber der einfachste Weg, dies zu tun, besteht darin, entweder ein System cp -aloder pax -rwlein System zu verwenden, für -ldas keine gültige Option besteht cp:

pax -rwl $DATA $DATA/../upgrade_tmp

oder

cp -al $DATA/ $DATA/../upgrade_tmp/
Jean-Philippe Pellet
quelle
4

Für mich geht das:

$ rsync --hard-links --recursive --link-dest=/local user@host:/remote/ /local

Ich benutze rsync Version 3.1.0.

Vom Menschen :

--hard-links

Weist rsync an, bei der Übertragung nach fest verknüpften Dateien zu suchen. Ohne diese Option werden fest verknüpfte Dateien bei der Übertragung so behandelt, als wären sie separate Dateien.

--link-dest = DIR

Unveränderte Dateien sind fest mit dem Zielverzeichnis verbunden. Die Dateien müssen in allen erhaltenen Attributen (z. B. Berechtigungen, möglicherweise Eigentumsrechte) identisch sein, damit die Dateien miteinander verknüpft werden können

Alexander Fedorov
quelle
2
Nur Code-Snippet ist nicht genug, erklären Sie, was es tut und warum.
Peter sagt, dass Monica am
--hard-links Weist rsync an, bei der Übertragung nach fest verknüpften Dateien zu suchen. Ohne diese Option werden fest verknüpfte Dateien bei der Übertragung so behandelt, als wären sie separate Dateien. --link-dest = DIR Unveränderte Dateien sind fest mit dem Zielverzeichnis verbunden. Die Dateien müssen in allen erhaltenen Attributen (z. B. Berechtigungen, möglicherweise Eigentumsrechte) identisch sein, damit die Dateien miteinander verknüpft werden können.
Alexander Fedorov
1
Wunderbar Vielen Dank. Eigentlich habe ich Ihre Antwort in der Warteschlange "niedrige Qualität" gefunden. Es wurde abgestimmt, ob Ihre Antwort gelöscht werden soll oder nicht. Aber nicht nur die Gefahr der Löschung ist ein Grund, zu versuchen, eine gut formatierte, "menschliche" Antwort zu geben, sondern es hilft auch sehr, wenn Sie eine Gegenstimme sammeln möchten.
Peter sagt, Monica
2

Sie können versuchen, dem Link http://www.lessfs.com/wordpress/ zu folgen. Es handelt sich um eine COW-Funktion (Copy on Write), die Zeit und Platz spart

Rajat
quelle
lessfs ist sehr interessant, aber auch sehr experimentell. Noch nicht für die Produktion empfohlen.
Mattdm
2

Erstellen Sie zuerst die Verzeichnisse nur auf dem Ziel:

rsync -av --include '*/' --exclude '*' /source/ /destination/

Dann verlinke nur die Dateien:

cd /source
find . -type f -exec ln -v {} /destination/{} \;
Cakemox
quelle
Danke - eigentlich könnte ich genauso gut paxwie in meinem Kommentar oben gezeigt, was einfacher zu sein scheint.
Jean-Philippe Pellet
1

Verwenden Sie die Option -H, um Hardlinks beizubehalten und die Manpage zu lesen.

tex
quelle
1
-H funktioniert nicht. Ich muss keine Hardlinks in meinem Quellbaum beibehalten. Ich möchte nur eine einfache Kopie meines Quellbaums, in der alle Dateien mit den Originaldateien verknüpft sind. Entschuldigung, in meiner ursprünglichen Frage war unklar ...
Jean-Philippe Pellet
Ist "read the manpage" eine Antwort? :-)
meduz