rsync, supprime les fichiers côté réception qui ont été supprimés côté envoi. (Mais ne supprimez pas tout)

9

Je voudrais utiliser rsync pour ...

  • supprimer les fichiers côté réception qui ont également été supprimés côté envoi
  • ne supprime pas les autres fichiers qui se trouvent dans le répertoire rsynced côté réception

Par exemple, disons que j'ai un répertoire local-src:

AVANT: local-src contient localement ...

a.txt
b.txt
c.txt

mon répertoire distant que je voudrais synchroniser avec le contenu de local-srcs'appelle remote-src.

AVANT: remote-src contient à distance ...

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

Disons que je supprime certains fichiers dans local-src:

APRÈS SUPPRESSION LOCALE: local-src contient localement ...

c.txt

Comment puis-je utiliser rsync de manière à garantir que les fichiers supprimés à la source sont également supprimés à la destination, mais sans supprimer d'autres fichiers à la destination. Par exemple, j'aimerais avoir les éléments suivants à destination:

APRÈS EFFACEMENT LOCAL: remote-src contient à distance ...

c.txt
d.txt
README.md

Autrement dit, a.txtet b.txtsont également supprimés à distance, mais d.txtet README.txtsont laissés seuls.

Existe-t-il un moyen d'y parvenir avec rsync?

EDIT: Le verdict semble être que cela pourrait être impossible avec rsync. On m'a demandé pourquoi j'avais besoin de cela, alors pour illustrer mon cas d'utilisation:

Disons que j'ai un serveur Web. Sur ce serveur Web, j'ai un tas de répertoires, disons que j'ai un répertoire Aet un public_htmlrépertoire à partir duquel mon site est servi. Disons que j'ai un processus automatisé qui produit des fichiers dans le répertoire A. Je voudrais rsync (ou synchroniser en utilisant un autre outil) les fichiers générés ou mis à jour dans Ale public_htmlrépertoire, sans supprimer d'autres fichiers arbitraires qui pourraient se trouver à l'intérieur public_html. Je ne veux certainement pas que rsync supprime accidentellement mon site Web.

Si rsync n'est pas l'outil pour ce travail, quelqu'un d'autre sait-il comment je peux le faire?

Heather Miller
la source
2
Après avoir relu votre question, je ne pense pas que ce soit possible rsynccar il n'y a aucun moyen de savoir quels fichiers se trouvent déjà dans le dossier distant. Vous devrez peut-être trouver un autre outil.
Spack
rsync ne vous laissera pas faire cela, mais si vous scpez le répertoire entier à chaque fois que vous supprimez des fichiers, vous pouvez les garder synchronisés, pas une solution juste une suggestion.
Aadi Droid
1
Je suppose que vous y avez déjà pensé, mais ne pourriez-vous pas simplement mettre ces fichiers dans un sous-répertoire (ou ailleurs) et les référencer à partir de public_html? De cette façon, vous avez un répertoire qui est facilement et explicitement synchronisé, sans affecter les fichiers dans d'autres parties du système de fichiers du serveur Web.
MattJenko

Réponses:

2

Ce que vous voulez faire est raisonnable, mais rsyncne pas le faire seul. La réponse est donc non .

La raison est simple: rsyncne conserve aucun historique de ce qui était dans chaque répertoire et n'a aucun moyen de savoir ce qui doit être supprimé et ce qui ne l'est pas. Pas sans support supplémentaire.

Vous devriez vous demander pourquoi vous aimez faire cela rsyncet clarifier cela. Il existe d'autres programmes qui utilisent librsync1.soplus intelligents.


Avec les contraintes détendues dont vous n'avez pas besoin en rsyncsoi, vous pouvez jeter un œil à rdiff-backup :

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

Cela se voit xxet yyest dans b.

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

Cela se voit xxet zzest dans b. rdiff-backupmaintient également un répertoire rdiff-backup-dataen bsorte que vous pouvez annuler ces modifications, vous devez purger sur une base régulière en utilisant les rdiff-backupcommandes. (L'exemple est avec des fichiers locaux pour montrer que les données supplémentaires dans la cible ne sont pas supprimées, mais rdiff-backup fonctionne également sur un réseau).


Une autre alternative consiste à configurer un système de contrôle de révision distribué (mercurial, bazaar, git). Avec mercurial, par exemple, vous pouvez avoir un script (j'utilise un Makefile pour cela), qui pousse toutes les modifications sur le serveur et fait ensuite une mise à jour des fichiers extraits, ignorez tous les fichiers supplémentaires qui se trouvent sur le serveur distant (mais qui ont pas été soumis au contrôle des révisions).

Sur le serveur, vous feriez:

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

Sur le client:

hg clone ssh://username@server/dir_to_repository

Maintenant, si vous supprimez un fichier sur le client et faites:

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

Votre fichier supprimé est supprimé sur le serveur, mais aucune autre donnée (non ajoutée au référentiel) n'est supprimée.

Anthon
la source
Je peux accepter que rsync ne le fasse pas. Mais je ne suis pas d'accord que ce serait impossible avec rsync - si rsync sait du côté de l'envoi quels fichiers ont été supprimés, pourquoi ne peut-il pas envoyer ces informations au côté de réception dans le diff? Après avoir comparé pour la fraîcheur, je ne vois pas pourquoi le côté récepteur ne peut pas simplement supprimer les fichiers qui ont été indiqués pour être supprimés dans le diff, sans supprimer tout le reste dans le répertoire. La suppression de tout autre fichier innocent (non supprimé à la source) dans le répertoire me semble déraisonnable.
Heather Miller
Dans tous les cas, la raison pour laquelle j'en ai besoin est la suivante. J'ai un répertoire, appelons-le A, où certains processus sont automatisés et les fichiers y sont générés automatiquement. J'ai un serveur Web et j'aimerais que les fichiers Aqu'ils contiennent soient synchronisés avec le public_htmlrépertoire du serveur Web, bien sûr sans supprimer tout le reste du public_htmldossier du serveur Web. Si quelqu'un a des idées pour y parvenir avec un autre outil, ce serait plus que bienvenu. Je mettrai à jour ma question pour refléter cela.
Heather Miller
Pour clarifier mon premier commentaire ci-dessus, j'aurais dû dire "Je ne suis pas d'accord que quelque chose comme ça devrait être impossible avec un outil comme rsync". Intuitivement, il semble que cela ne soit pas trop difficile à réaliser (sauf si je manque quelque chose).
Heather Miller
Hmm, d'accord. Je pense que je vois maintenant - comment rsync peut-il savoir quand quelque chose a été supprimé dans le local-srcrépertoire sans qu'un processus ne surveille ce répertoire pour les changements. Ce serait peut-être difficile.
Heather Miller
@HeatherMiller Comme je l'ai écrit, votre demande est raisonnable, mais ce rsyncn'est pas l'outil. S'il vous plaît se rendre compte que syncdans rsyncvient de synchronisation et ce n'est pas exactement ce que vous voulez faire. Dans le développement de rsyncl'accent a été mis sur l'efficacité (minimiser) le transfert de données. D'autres outils comme rdiff-backup(et possibles cvsup) ont utilisé ses techniques pour cela, mais s'appuient sur lui avec des fonctionnalités supplémentaires.
Anthon
1

Je ne pense pas que cela soit possible sans exclure explicitement les fichiers du côté réception dans le cadre de la commande rsync. Consultez la section de la page de manuel pour rsync: "RÈGLES PAR RÉPERTOIRE ET SUPPRIMER".

Sans option de suppression, les règles par répertoire ne sont pertinentes que du côté de l'envoi, vous pouvez donc vous sentir libre d'exclure les fichiers de fusion eux-mêmes sans affecter le transfert. Pour rendre cela facile, le modificateur «e» ajoute cette exclusion pour vous, comme on le voit dans ces deux commandes équivalentes:

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

Toutefois, si vous souhaitez effectuer une suppression côté réception ET que certains fichiers doivent être exclus de la suppression, vous devez vous assurer que le côté réception connaît les fichiers à exclure. Le moyen le plus simple consiste à inclure les fichiers de fusion par répertoire dans le transfert et à utiliser --delete-after, car cela garantit que le côté récepteur reçoit les mêmes règles d'exclusion que le côté expéditeur avant d'essayer de supprimer quoi que ce soit:

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

Cependant, si les fichiers de fusion ne font pas partie du transfert, vous devrez soit spécifier des règles d'exclusion globales (c'est-à-dire spécifiées sur la ligne de commande), soit conserver vos propres fichiers de fusion par répertoire sur le côté réception. Voici un exemple du premier (supposez que les fichiers .rules distants s'excluent):

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

Dans l'exemple ci-dessus, le fichier extra.rules peut affecter les deux côtés du transfert, mais (du côté de l'envoi) les règles sont subordonnées aux règles fusionnées à partir des fichiers .rules car elles ont été spécifiées après la règle de fusion par répertoire.

Dans un dernier exemple, le côté distant exclut les fichiers de filtre .rsync du transfert, mais nous voulons utiliser nos propres fichiers de filtre .rsync pour contrôler ce qui est supprimé du côté récepteur. Pour ce faire, nous devons spécifiquement exclure les fichiers de fusion par répertoire (afin qu'ils ne soient pas supprimés), puis mettre des règles dans les fichiers locaux pour contrôler ce qui ne doit pas être supprimé. Comme l'une de ces commandes:

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

Si j'ai bien compris, c'est --excludepeut-être ce que vous cherchez:

$ 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
la source
Et bien non. Je ne veux pas avoir à répertorier manuellement tous les fichiers que j'aimerais exclure. Je voudrais juste que rsync supprime uniquement les fichiers que j'ai supprimés à la source - je ne devrais pas avoir à savoir à la source quels autres fichiers possibles existent dans le même répertoire à la destination.
Heather Miller
0

J'ai une réponse à cela. Je pense que ça marche. Et cela fonctionne pour moi . Vous devez d'abord avoir à rsyncdistance des fichiers vers des fichiers locaux. Ensuite, le côté local contient tous les fichiers.

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

maintenant côté local

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

Ensuite, vous pouvez supprimer les fichiers ou faire ce que vous voulez (côté local). Dans votre question, vous supprimez ces fichiers.

fichiers supprimés

a.txt
b.txt

Après cela, vous pouvez rsynccréer des fichiers locaux sur le côté distant.

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

il donne

c.txt
d.txt
README.md

fichiers du côté distant et du côté local (en utilisant --delete, il supprime les autres fichiers du côté distant qui ne correspondent pas au côté local ).

Thusitha Sumanadasa
la source