rsync, elimina i file sul lato di ricezione che sono stati eliminati sul lato di invio. (Ma non cancellare tutto)


9

Vorrei usare rsync per ...

  • eliminare i file sul lato ricevente che sono stati eliminati anche sul lato di invio
  • non eliminare altri file che si trovano nella directory rsynced sul lato ricevente

Ad esempio, supponiamo che io abbia una directory local-src:

PRIMA: local-src contiene localmente ...

a.txt
b.txt
c.txt

local-srcviene chiamata la mia directory remota che vorrei sincronizzare con il contenuto di to remote-src.

PRIMA: remote-src contiene in remoto ...

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

Diciamo che elimino alcuni file in local-src:

DOPO L'ELIMINAZIONE LOCALE: local-src contiene localmente ...

c.txt

Come posso utilizzare rsync in modo da garantire che anche i file eliminati all'origine vengano eliminati nella destinazione, ma senza eliminare altri file nella destinazione. Ad esempio, vorrei avere quanto segue a destinazione:

DOPO L'ELIMINAZIONE LOCALE: remote-src contiene in remoto ...

c.txt
d.txt
README.md

Cioè, a.txte b.txtvengono eliminati anche in remoto, ma d.txte README.txtvengono lasciati soli.

C'è un modo per raggiungere questo obiettivo con rsync?

EDIT: Il verdetto sembra essere che questo potrebbe essere impossibile con rsync. Mi è stato chiesto perché ne ho bisogno, quindi per illustrare il mio caso d'uso:

Diciamo che ho un web server. Su quel web server, ho un sacco di directory, diciamo che ho una directory Ae una public_htmldirectory da cui viene servito il mio sito. Diciamo che ho un processo automatizzato che produce file nella directory A. Mi piacerebbe rsync (o sincronizzare con qualche altro strumento) i file generati o aggiornati in Aalla public_htmldirectory, senza cancellare altri file arbitrari che potrebbero essere all'interno public_html. Non voglio certo che rsync elimini accidentalmente il mio sito web.

Se rsync non è lo strumento per questo lavoro, qualcun altro sa come posso farlo?


2
Dopo aver riletto la tua domanda, non penso che ciò sia possibile in rsyncquanto non c'è modo di sapere quali file fossero già nella cartella remota. Potrebbe essere necessario scoprire un altro strumento.
Spacca

rsync non ti consente di farlo, ma se scp l'intera directory ogni volta che elimini i file puoi tenerli sincronizzati, non una soluzione solo un suggerimento.
Aadi Droid,

1
Immagino che tu ci abbia già pensato, ma non potresti semplicemente mettere questi file in una sottodirectory (o da qualche altra parte) e fare riferimento a loro da public_html? In questo modo hai una directory che può essere sincronizzata facilmente ed esplicitamente, senza influire sui file in altre parti del filesystem del server web.
MattJenko

Risposte:


2

Quello che vuoi fare è ragionevole, ma usarlo rsyncper conto proprio non lo è. Quindi la risposta è no .

Il motivo è semplice: rsyncnon conserva alcuna cronologia di ciò che era in ogni directory e non ha modo di sapere cosa deve essere cancellato e cosa no. Non senza supporto aggiuntivo.

Dovresti chiederti perché ti piace farlo rsynce renderlo più chiaro. Ci sono altri programmi che usano librsync1.soche sono più intelligenti.


Con i vincoli rilassati di cui non hai bisogno di rsyncper sé, puoi dare un'occhiata a rdiff-backup :

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

Questo mostra xxe yysono dentro b.

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

Questo mostra xxe zzsono dentro b. rdiff-backupmantiene anche una directory rdiff-backup-datain bmodo da poter eseguire il rollback di qualsiasi modifica, è necessario eliminarla regolarmente utilizzando i rdiff-backupcomandi. (L'esempio è con i file locali per mostrare dati extra nella destinazione non vengono cancellati, ma rdiff-backup funziona anche su una rete).


Un'altra alternativa è installare un sistema di controllo di revisione distribuito (mercurial, bazaar, git). Con mercurial, ad esempio, puoi avere uno script (io uso un Makefile per quello), che invia tutte le modifiche al server e quindi fa un aggiornamento dei file estratti lì, ignora tutti i file aggiuntivi che si trovano sul server remoto (ma hanno non sottoposto a controllo di revisione).

Sul server faresti:

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

Sul cliente:

hg clone ssh://username@server/dir_to_repository

Ora se rimuovi un file sul client e fai:

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

Il file rimosso viene rimosso sul server, ma tutti gli altri dati (non aggiunti al repository) non vengono eliminati.


Posso accettare che rsync non lo farà. Ma non sono d'accordo sul fatto che questo sarebbe impossibile con rsync: se rsync sa dal lato di invio quali file sono stati eliminati, perché non può inviare tali informazioni al lato ricevente nel diff? Dopo aver confrontato per aggiornamento, non vedo perché il lato ricevente non può semplicemente eliminare i file che sono stati indicati per essere eliminati nel diff, senza eliminare tutto il resto nella directory. Eliminare ogni altro file innocente (non cancellato alla fonte) nella directory mi sembra irragionevole.
Heather Miller,

In ogni caso, il motivo per cui ho bisogno di questo è il seguente. Ho una directory, chiamiamola A, in cui alcuni processi sono automatizzati e i file vengono generati automaticamente lì. Ho un web server e vorrei che i file all'interno Avenissero sincronizzati nella public_htmldirectory del server web, ovviamente senza cancellare tutto il resto nella public_htmlcartella del web server. Se qualcuno ha qualche idea per raggiungerlo con un altro strumento, sarebbe più che benvenuto. Aggiornerò la mia domanda per riflettere questo.
Heather Miller,

Per chiarire il mio primo commento sopra, avrei dovuto dire "Non sono d'accordo sul fatto che qualcosa del genere dovrebbe essere impossibile con uno strumento come rsync". Intuitivamente, sembra che questo non possa essere troppo difficile da raggiungere (a meno che non mi manchi qualcosa).
Heather Miller,

Hmm va bene. Penso di vedere ora- come posso sapere se rsync quando qualcosa è stato cancellato nella local-srcdirectory senza avere qualche processo a guardare quella directory per le modifiche. Forse questo sarebbe difficile.
Heather Miller,

@HeatherMiller Come ho scritto, la tua richiesta è ragionevole, ma rsyncnon è lo strumento. Tieni presente che syncin rsyncproviene dalla sincronizzazione e che non è esattamente quello che vuoi fare. Nello sviluppo rsyncdell'attenzione si è concentrato sull'efficace (minimizzazione) del trasferimento di dati. Altri strumenti come rdiff-backup(e possibili cvsup) hanno usato le sue tecniche per questo, ma si basano su di esso con funzionalità aggiuntive.
Anthon,

1

Non penso che ciò sia possibile senza escludere esplicitamente i file sul lato ricevente come parte del comando rsync. Vedere la sezione della pagina man per rsync: "REGOLE E CANCELLAZIONE PER DIRECTORY".

Senza un'opzione di eliminazione, le regole per directory sono rilevanti solo dal lato di invio, quindi puoi sentirti libero di escludere i file di unione senza influire sul trasferimento. Per rendere tutto più semplice, il modificatore 'e' aggiunge questa esclusione per te, come si vede in questi due comandi equivalenti:

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

Tuttavia, se si desidera eseguire un'eliminazione sul lato ricevente E si desidera che alcuni file vengano esclusi dall'eliminazione, è necessario assicurarsi che il lato ricevente sappia quali file escludere. Il modo più semplice è includere i file di unione per directory nel trasferimento e usare --delete-after, perché questo assicura che il lato ricevente ottenga le stesse regole di esclusione del lato mittente prima di provare a cancellare qualcosa:

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

Tuttavia, se i file di unione non fanno parte del trasferimento, è necessario specificare alcune regole di esclusione globali (ovvero specificate nella riga di comando) oppure è necessario mantenere i propri file di unione per directory nella lato ricevente. Un esempio del primo è questo (supponiamo che i file .rules remoti si escludano):

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

Nell'esempio precedente il file extra.rules può influire su entrambi i lati del trasferimento, ma (sul lato di invio) le regole sono subordinate alle regole unite dai file .rules perché sono state specificate dopo la regola di unione per directory.

In un ultimo esempio, il lato remoto esclude i file .rsync-filter dal trasferimento, ma vogliamo usare i nostri file .rsync-filter per controllare ciò che viene eliminato sul lato ricevente. Per fare ciò dobbiamo escludere specificamente i file di unione per directory (in modo che non vengano eliminati) e quindi inserire le regole nei file locali per controllare cos'altro non dovrebbe essere eliminato. Come uno di questi comandi:

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

0

Se ho capito bene, --excludepotrebbe essere quello che stai cercando:

$ 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

Beh no. Non voglio elencare manualmente tutti i file che vorrei escludere. Vorrei solo che rsync cancellasse solo i file che ho cancellato alla fonte. Non avrei dovuto sapere alla fonte quali altri file possibili esistono nella stessa directory nella destinazione.
Heather Miller,

0

Ho una risposta per questo. Penso che funzioni E funziona per me. Per prima cosa dovresti dover rsyncremotare i file in file locali. Quindi il lato locale contiene tutti i file.

sudo rsync -r -a -v --delete /root@xx.xx.xx.xx:/remote_dir/ /local_dir/

ora nella parte locale

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

Quindi è possibile eliminare i file o fare ciò che si desidera (nel lato locale). Nella tua domanda, elimini questi file.

file cancellati

a.txt
b.txt

Dopodiché puoi rsyncfile locali sul lato remoto, quindi entrambi i lati hanno gli stessi file.

sudo rsync -r -a -v --delete /local_dir/ root@xx.xx.xx.xx:/remote_dir/

c.txt
d.txt
README.md

file sul lato remoto e sul lato locale (utilizzando --delete, elimina altri file sul lato remoto che non corrispondono al lato locale ).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.