rsync, löscht Dateien auf der Empfangsseite, die auf der Sendeseite gelöscht wurden. (Aber nicht alles löschen)

9

Ich möchte rsync verwenden, um ...

  • Löschen Sie Dateien auf der empfangenden Seite, die auch auf der sendenden Seite gelöscht wurden
  • Löschen Sie keine anderen Dateien, die sich auf der Empfangsseite im Verzeichnis rsynced befinden

Nehmen wir zum Beispiel an, ich habe ein Verzeichnis local-src:

VORHER: local-src lokal enthält ...

a.txt
b.txt
c.txt

Mein Remote-Verzeichnis, das ich mit dem Inhalt von local-srcto synchronisieren möchte , wird aufgerufen remote-src.

VORHER: remote-src Enthält ...

a.txt
b.txt
c.txt
d.txt
README.md

Angenommen, ich lösche einige Dateien in local-src:

AFTER LOCAL DELETE: local-src enthält lokal ...

c.txt

Wie kann ich rsync verwenden, um sicherzustellen, dass die an der Quelle gelöschten Dateien auch am Ziel gelöscht werden, ohne jedoch andere Dateien am Ziel zu löschen? Zum Beispiel möchte ich Folgendes am Zielort haben:

AFTER LOCAL DELETE: remote-src enthält ...

c.txt
d.txt
README.md

Das heißt, a.txtund b.txtwerden auch aus der Ferne gelöscht, aber d.txtund README.txtwerden in Ruhe gelassen.

Gibt es eine Möglichkeit, dies mit rsync zu erreichen?

EDIT: Das Urteil scheint zu sein, dass dies mit rsync unmöglich sein könnte. Ich wurde gefragt, warum ich das brauche, um meinen Anwendungsfall zu veranschaulichen:

Angenommen, ich habe einen Webserver. Auf diesem Webserver habe ich eine Reihe von Verzeichnissen. Nehmen wir an, ich habe ein Verzeichnis Aund ein public_htmlVerzeichnis, aus dem meine Site bereitgestellt wird . Angenommen, ich habe einen automatisierten Prozess, der Dateien im Verzeichnis erstellt A. Ich möchte die generierten oder in das Verzeichnis aktualisierten Dateien rsync (oder mit einem anderen Tool synchronisieren) , ohne andere beliebige Dateien zu löschen, die sich möglicherweise darin befinden . Ich möchte auf keinen Fall, dass rsync meine Website versehentlich löscht.Apublic_htmlpublic_html

Wenn rsync nicht das Werkzeug für diesen Job ist, weiß jemand anderes, wie ich das tun kann?

Heather Miller
quelle
2
Nach dem erneuten Lesen Ihrer Frage glaube ich nicht, dass dies möglich ist, rsyncda nicht festgestellt werden kann, welche Dateien sich bereits im Remote-Ordner befinden. Möglicherweise müssen Sie ein anderes Tool herausfinden.
Spack
rsync lässt Sie dies nicht zu, aber wenn Sie jedes Mal, wenn Sie Dateien löschen, das gesamte Verzeichnis durchsuchen, können Sie sie synchron halten, keine Lösung, sondern nur ein Vorschlag.
Aadi Droid
1
Ich vermute, Sie haben bereits darüber nachgedacht, aber könnten Sie diese Dateien nicht einfach in ein Unterverzeichnis (oder woanders) stellen und von public_html aus darauf verweisen? Auf diese Weise haben Sie ein Verzeichnis, das einfach und explizit synchronisiert werden kann, ohne dass sich dies auf Dateien in anderen Teilen des Dateisystems des Webservers auswirkt.
MattJenko

Antworten:

2

Was Sie tun möchten, ist vernünftig, aber rsynces ist nicht sinnvoll, es alleine zu tun. Die Antwort lautet also nein .

Der Grund ist einfach: Er rsyncführt keinen Verlauf dessen, was sich in jedem Verzeichnis befand, und kann nicht wissen, was gelöscht werden muss und was nicht. Nicht ohne zusätzliche Unterstützung.

Sie sollten sich fragen, warum Sie dies gerne tun, und dies rsyncklarer machen. Es gibt andere Programme, die librsync1.sointelligenter sind.


Mit den entspannten Einschränkungen, die Sie rsyncper se nicht benötigen , können Sie sich rdiff-backup ansehen :

mkdir a
touch a/xx
touch a/yy
rdiff-backup a b
ls b 

Dies zeigt xxund yysind in b.

touch b/zz
rm a/xx
rdiff-backup a b

Dies zeigt xxund zzsind in b. rdiff-backuphält auch ein Verzeichnis rdiff-backup-datain bso dass Sie alle Änderungen Rollback können, sollten Sie diese in regelmäßigen Abständen spülen , indem rdiff-backupBefehle. (Das Beispiel ist mit lokalen Dateien, die zeigen, dass zusätzliche Daten im Ziel nicht gelöscht werden, aber rdiff-backup funktioniert auch über ein Netzwerk).


Eine andere Alternative besteht darin, ein verteiltes Revisionskontrollsystem (Quecksilber, Basar, Git) einzurichten. Mit mercurial können Sie beispielsweise ein Skript haben (ich verwende dafür ein Makefile), das alle Änderungen auf den Server überträgt und dann die dort ausgecheckten Dateien aktualisiert. Ignorieren Sie alle zusätzlichen Dateien, die sich auf dem Remote-Server befinden (aber haben) nicht unter Revisionskontrolle gestellt).

Auf dem Server würden Sie tun:

hg init
hg add file_list_excluding_that_should_not_should_be_deleted_if_not_on_client
hg commit -m "initial setup"

Auf dem Client:

hg clone ssh://username@server/dir_to_repository

Wenn Sie nun eine Datei auf dem Client entfernen und Folgendes tun:

hg commit -m "removed file"
ssh username@server "cd dir_to_repository; hg update --clean"

Ihre entfernte Datei wird auf dem Server entfernt, aber alle anderen Daten (nicht zum Repository hinzugefügt) werden nicht gelöscht.

Anthon
quelle
Ich kann akzeptieren, dass rsync dies nicht tut. Aber ich stimme nicht zu, dass dies mit rsync unmöglich wäre. Wenn rsync auf der sendenden Seite weiß, welche Dateien gelöscht wurden, warum kann es diese Informationen nicht an die empfangende Seite im Diff senden? Nach dem Vergleich auf Frische sehe ich nicht, warum die empfangende Seite nicht einfach die Dateien löschen kann, deren Löschung im Diff angegeben wurde, ohne alles andere im Verzeichnis zu löschen. Das Löschen jeder anderen (an der Quelle nicht gelöschten) unschuldigen Datei im Verzeichnis erscheint mir unvernünftig.
Heather Miller
Der Grund, warum ich das brauche, ist auf jeden Fall wie folgt. Ich habe ein Verzeichnis, nennen wir es A, in dem ein Prozess automatisiert wird und dort automatisch Dateien generiert werden. Ich habe einen Webserver und möchte, dass die darin enthaltenen Dateien Ain das public_htmlVerzeichnis des Webservers synchronisiert werden , natürlich ohne alles andere im public_htmlOrdner des Webservers zu löschen . Wenn jemand Ideen hat, um dies mit einem anderen Tool zu erreichen, wäre dies mehr als willkommen. Ich werde meine Frage aktualisieren, um dies widerzuspiegeln.
Heather Miller
Um meinen ersten Kommentar oben zu verdeutlichen, hätte ich sagen sollen: "Ich bin nicht der Meinung, dass so etwas mit einem Tool wie rsync unmöglich sein sollte." Intuitiv scheint es nur so, als ob dies nicht zu schwer zu erreichen sein kann (es sei denn, ich vermisse etwas).
Heather Miller
Hmm, OK. Ich denke, ich sehe jetzt - wie kann rsync wissen, wann etwas im local-srcVerzeichnis gelöscht wurde, ohne dass ein Prozess dieses Verzeichnis auf Änderungen überwacht. Vielleicht wäre das schwierig.
Heather Miller
@HeatherMiller Wie ich geschrieben habe, ist Ihre Anfrage vernünftig, aber rsyncnicht das Werkzeug. Bitte beachten Sie, dass syncin rsyncvon der Synchronisierung kommt und das nicht genau das ist, was Sie tun möchten. Bei der Entwicklung des rsyncFokus lag der Schwerpunkt auf einer effizienten (Minimierung) der Datenübertragung. Andere Tools wie rdiff-backup(und möglich cvsup) haben ihre Techniken dafür verwendet, bauen aber mit zusätzlichen Funktionen darauf auf.
Anthon
1

Ich denke nicht, dass dies möglich ist, ohne die Dateien auf der Empfangsseite als Teil des Befehls rsync explizit auszuschließen. Siehe den Manpage-Abschnitt für rsync: "PER-DIRECTORY RULES AND DELETE".

Ohne eine Löschoption sind die Regeln pro Verzeichnis nur auf der sendenden Seite relevant, sodass Sie die Zusammenführungsdateien selbst ausschließen können, ohne die Übertragung zu beeinträchtigen. Um dies zu vereinfachen, fügt der Modifikator 'e' diesen Ausschluss für Sie hinzu, wie in diesen beiden entsprechenden Befehlen dargestellt:

          rsync -av --filter=': .excl' --exclude=.excl host:src/dir /dest
          rsync -av --filter=':e .excl' host:src/dir /dest

Wenn Sie jedoch auf der Empfangsseite einen Löschvorgang durchführen möchten UND einige Dateien vom Löschen ausgeschlossen werden sollen, müssen Sie sicherstellen, dass die Empfangsseite weiß, welche Dateien ausgeschlossen werden sollen. Am einfachsten ist es, die Zusammenführungsdateien pro Verzeichnis in die Übertragung einzubeziehen und --delete-after zu verwenden, da dadurch sichergestellt wird, dass die empfangende Seite dieselben Ausschlussregeln wie die sendende Seite erhält, bevor sie versucht, etwas zu löschen:

          rsync -avF --delete-after host:src/dir /dest

Wenn die Zusammenführungsdateien jedoch nicht Teil der Übertragung sind, müssen Sie entweder einige globale Ausschlussregeln angeben (dh in der Befehlszeile angegeben), oder Sie müssen Ihre eigenen Zusammenführungsdateien pro Verzeichnis auf der Datei verwalten Empfangsseite. Ein Beispiel für das erste ist das folgende (nehmen Sie an, dass sich die Remote-Regeldateien selbst ausschließen):

   rsync -av --filter=’: .rules’ --filter=’. /my/extra.rules’
      --delete host:src/dir /dest

Im obigen Beispiel kann die Datei extra.rules beide Seiten der Übertragung betreffen, aber (auf der sendenden Seite) unterliegen die Regeln den Regeln, die aus den .rules-Dateien zusammengeführt wurden, da sie nach der Zusammenführungsregel pro Verzeichnis angegeben wurden.

In einem letzten Beispiel schließt die Remote-Seite die .rsync-Filterdateien von der Übertragung aus, aber wir möchten unsere eigenen .rsync-Filterdateien verwenden, um zu steuern, was auf der empfangenden Seite gelöscht wird. Dazu müssen wir die Zusammenführungsdateien pro Verzeichnis ausdrücklich ausschließen (damit sie nicht gelöscht werden) und dann Regeln in die lokalen Dateien einfügen, um zu steuern, was sonst nicht gelöscht werden soll. Wie einer dieser Befehle:

       rsync -av --filter=':e /.rsync-filter' --delete \
           host:src/dir /dest
       rsync -avFF --delete host:src/dir /dest
slm
quelle
0

Wenn ich richtig verstanden habe, --excludekönnte das das sein, wonach Sie suchen:

$ ls src dst
dst:
a.txt  b.txt  c.txt  d.txt  README.md

src:
c.txt
$ rsync --update --delete --recursive --exclude="d.txt" --exclude="README.md" src/ dst
$ ls src dst
dst:
c.txt  d.txt  README.md

src:
c.txt
Spack
quelle
Nun, nein. Ich möchte nicht alle Dateien, die ich ausschließen möchte, manuell auflisten müssen. Ich möchte nur, dass rsync nur die Dateien löscht, die ich an der Quelle gelöscht habe. Ich sollte an der Quelle nicht wissen müssen, welche anderen möglichen Dateien im selben Verzeichnis am Ziel vorhanden sind.
Heather Miller
0

Ich habe eine Antwort darauf. Ich denke es funktioniert. Und es funktioniert bei mir. Zuerst sollten Sie rsyncDateien in lokale Dateien umwandeln müssen. Dann enthält die lokale Seite alle Dateien.

sudo rsync -r -a -v --delete /[email protected]:/remote_dir/ /local_dir/

jetzt auf lokaler Seite

a.txt
b.txt
c.txt
d.txt
README.md

Dann können Sie die Dateien löschen oder tun, was Sie wollen (auf lokaler Seite). In Ihrer Frage löschen Sie diese Dateien.

gelöschte Dateien

a.txt
b.txt

Danach können Sie rsynclokale Dateien auf der Remote-Seite. Dann haben beide Seiten die gleichen Dateien.

sudo rsync -r -a -v --delete /local_dir/ [email protected]:/remote_dir/

es gibt

c.txt
d.txt
README.md

Dateien auf der Remote-Seite und der lokalen Seite. (Durch die Verwendung --deletewerden andere Dateien auf der Remote-Seite gelöscht , die nicht mit der lokalen Seite übereinstimmen .)

Thusitha Sumanadasa
quelle