Salta al contenuto principale

rsync: sincronizzare e copiare file in modo efficiente

Inviato da tuxsa il

rsync copia file e cartelle come cp, ma in modo più intelligente: trasferisce solo ciò che è cambiato, può lavorare tra computer diversi attraverso SSH e permette di mantenere due cartelle identiche. È lo strumento classico per backup, migrazioni di siti e copie di grandi quantità di dati.

Cos'è

rsync sta per remote synchronization. Il suo punto di forza è l'algoritmo che confronta origine e destinazione e invia soltanto le differenze: la prima copia trasferisce tutto, le successive molto meno. Funziona in locale (da una cartella a un'altra) e in rete, di solito attraverso ssh. Su Debian e Ubuntu è nel pacchetto rsync: sudo apt install rsync. Per i trasferimenti in rete deve essere installato su entrambe le macchine.

Cosa fa

Confronta i file dell'origine con quelli della destinazione (per impostazione predefinita guarda dimensione e data di modifica), copia quelli nuovi o modificati e, se glielo chiedi, può anche cancellare dalla destinazione ciò che nell'origine non esiste più. Può conservare permessi, proprietari, date e collegamenti simbolici, riprendere un trasferimento interrotto e mostrare cosa farebbe senza toccare nulla.

Come si usa

$ rsync [opzioni] ORIGINE DESTINAZIONE

L'origine o la destinazione possono essere remote, con la forma utente@host:percorso, la stessa di scp. Gli indirizzi e i nomi negli esempi (server.example.org, l'utente enzo, i percorsi) sono d'esempio: sostituiscili con i tuoi.

Esempio 1: la forma base, in locale

$ ls progetto/
index.html  stile.css  immagini
$ rsync -av progetto/ copia/
sending incremental file list
created directory copia
./
index.html
stile.css
immagini/
immagini/logo.png

sent 48.317 bytes  received 118 bytes  96.870,00 bytes/sec
total size is 47.985  speedup is 0,99

Le opzioni -a (archive) e -v (verbose) sono la combinazione di base: -a copia le cartelle in modo ricorsivo e conserva permessi, proprietari, date e collegamenti simbolici; -v elenca i file trasferiti. Riga per riga: l'elenco dei file copiati, poi i byte inviati e la dimensione totale.

Esempio 2: la barra finale cambia tutto

$ rsync -av progetto/ copia/
$ ls copia/
index.html  stile.css  immagini

$ rsync -av progetto copia/
$ ls copia/
progetto

Questo è il dettaglio più importante di rsync. Con la barra finale sull'origine (progetto/) si copia il contenuto della cartella; senza barra (progetto) si copia la cartella stessa, che finisce dentro la destinazione. La barra sulla destinazione, invece, non cambia nulla. Nel dubbio, prova prima con -n (vedi l'esempio successivo).

Esempio 3: simulare prima con -n

$ rsync -avn progetto/ copia/
sending incremental file list
index.html

sent 83 bytes  received 19 bytes  204,00 bytes/sec
total size is 47.985  speedup is 470,44 (DRY RUN)

Con -n (dry run) rsync mostra cosa farebbe senza copiare né cancellare niente. La scritta (DRY RUN) alla fine conferma che è solo una prova. È un'abitudine da prendere ogni volta che si usano percorsi nuovi o opzioni come --delete.

Esempio 4: la seconda volta si copia solo il cambiato

$ echo "nuova riga" >> progetto/index.html
$ rsync -av progetto/ copia/
sending incremental file list
index.html

sent 1.152 bytes  received 47 bytes  2.398,00 bytes/sec
total size is 48.010  speedup is 40,04

Ripetendo il comando vengono trasferiti solo i file modificati: qui index.html. Con file grandi, rsync invia addirittura soltanto le parti diverse del file. Se non è cambiato niente, l'elenco è vuoto e il comando termina in un attimo.

Esempio 5: copiare verso un server (e da un server)

$ rsync -avz progetto/ enzo@server.example.org:/home/enzo/progetto/
$ rsync -avz enzo@server.example.org:/var/www/sito/ ./sito-locale/
$ rsync -avz -e "ssh -p 2222" progetto/ web:/home/enzo/progetto/

Con la forma utente@host:percorso rsync si collega via SSH (con le stesse chiavi e lo stesso file ~/.ssh/config di ssh: quindi funzionano anche i nomi brevi, come web). L'opzione -z comprime i dati durante il trasferimento, utile su connessioni lente. Con -e si indica il comando da usare per il collegamento, per esempio per cambiare la porta.

Esempio 6: avanzamento e riprese con -P

$ rsync -avP film.mkv enzo@server.example.org:/home/enzo/video/
sending incremental file list
film.mkv
    412.352.512  27%   38,15MB/s    0:00:28

-P è la scorciatoia di --progress --partial: mostra l'avanzamento di ogni file e conserva i file parziali. Se il trasferimento si interrompe, rilanciando lo stesso comando riprende dal punto in cui era arrivato, invece di ricominciare da capo.

Esempio 7: tenere due cartelle identiche con --delete

$ rm progetto/vecchio.txt
$ rsync -av --delete progetto/ copia/
sending incremental file list
deleting vecchio.txt

sent 67 bytes  received 12 bytes  158,00 bytes/sec
total size is 47.985  speedup is 607,41

Di norma rsync non cancella niente dalla destinazione. Con --delete elimina i file che nell'origine non esistono più, quindi la destinazione diventa una copia esatta. È utile per gli specchi (mirror) di un sito o di una cartella, ma è anche l'opzione più rischiosa (vedi più sotto): prova sempre prima con -n.

Esempio 8: escludere file e cartelle

$ rsync -av --exclude='*.tmp' --exclude='cache/' --exclude='.git/' progetto/ copia/
$ rsync -av --exclude-from=esclusioni.txt progetto/ copia/
$ cat esclusioni.txt
*.tmp
cache/
node_modules/

Con --exclude si saltano file o cartelle che corrispondono a un modello; con --exclude-from i modelli si leggono da un file, uno per riga. I modelli si riferiscono ai percorsi relativi all'origine. Un modello come /cache/ (con la barra iniziale) esclude solo quello nella cartella principale, mentre cache/ esclude qualsiasi cartella con quel nome. Esiste anche --include, per fare eccezioni, ma l'ordine delle regole conta: vince la prima che corrisponde.

Esempio 9: backup di un sito (un caso reale)

$ rsync -avz --delete \
    --exclude='sites/default/files/php/' \
    --exclude='sites/default/files/css/' \
    --exclude='sites/default/files/js/' \
    enzo@server.example.org:/var/www/sito/ /backup/sito/

Qui si scarica in locale una copia del sito web, escludendo le cartelle di cache che si rigenerano da sole (nell'esempio, quelle tipiche di Drupal). La prima esecuzione richiede tempo, le successive solo pochi secondi. I backup del solo codice e dei file non bastano per un sito con database: serve anche l'esportazione di quest'ultimo.

Esempio 10: backup con versioni, a spazio quasi costante

$ OGGI=$(date +%F)
$ rsync -a --delete --link-dest=/backup/ultimo /home/enzo/documenti/ /backup/$OGGI/
$ ln -sfn /backup/$OGGI /backup/ultimo

Con --link-dest i file che non sono cambiati rispetto al backup precedente non vengono copiati di nuovo: rsync crea un collegamento fisico (hard link, visto nell'articolo su ln) al file già presente. Ogni cartella datata sembra un backup completo, ma occupa solo lo spazio di ciò che è cambiato. L'ultimo comando aggiorna il collegamento simbolico ultimo perché punti all'ultimo backup. La prima volta la cartella /backup/ultimo non esiste e rsync avvisa, ma esegue comunque una copia completa. Funziona solo se origine e destinazione dei backup stanno sullo stesso file system, che deve supportare gli hard link.

Esempio 11: cosa è cambiato davvero con --itemize-changes

$ rsync -avin progetto/ copia/
.d..t...... ./
>f.st...... index.html
>f+++++++++ nuovo.txt

Con -i ogni riga comincia con una sigla di 11 caratteri che spiega perché il file è stato trasferito. In sintesi: >f è un file in arrivo sulla destinazione, +++++++++ indica un file nuovo, s una dimensione diversa, t una data diversa, d una cartella. Utile quando rsync copia file che dovrebbero essere uguali e vuoi capire il perché.

Esempio 12: limitare banda e dimensioni

$ rsync -avz --bwlimit=2000 --max-size=100m progetto/ web:/home/enzo/progetto/
$ rsync -a --stats --human-readable progetto/ copia/
Number of files: 142 (reg: 120, dir: 22)
Number of regular files transferred: 3
Total file size: 48,02M bytes
Total transferred file size: 1,15M bytes

--bwlimit limita la velocità (in KiB al secondo; 2000 sono circa 2 MB/s), così il trasferimento non satura la connessione. --max-size salta i file più grandi del limite. Con --stats e -h si ottiene un riepilogo leggibile alla fine.

Esempio 13: uso negli script

#!/bin/bash
ORIGINE="/home/enzo/documenti/"
DESTINAZIONE="web:/home/enzo/backup/documenti/"
LOG="$HOME/backup-rsync.log"

if rsync -az --delete --partial "$ORIGINE" "$DESTINAZIONE" >> "$LOG" 2>&1; then
    echo "$(date '+%F %T') backup riuscito" >> "$LOG"
else
    CODICE=$?
    echo "$(date '+%F %T') ERRORE rsync (codice $CODICE)" >> "$LOG"
    exit "$CODICE"
fi

Il codice di uscita di rsync è 0 se tutto è andato bene; i valori diversi da zero indicano un problema (per esempio 23 trasferimento parziale per errori su alcuni file, 24 file spariti durante la copia, 12 errore nel flusso dei dati, 255 errore di SSH). In uno script usato dal cron non devono esserci richieste di password: serve l'accesso a chiave (vedi l'articolo su ssh). Lo script va reso eseguibile con chmod +x.

Opzioni utili

  • -a: modo archivio (ricorsivo, conserva permessi, proprietari, date, collegamenti simbolici); è equivalente a -rlptgoD.
  • -v / -q: più dettagli / silenzioso; -h: dimensioni leggibili; -i: spiega i cambiamenti.
  • -n (--dry-run): simulazione, non cambia nulla.
  • -z: comprime durante il trasferimento (inutile per file già compressi, come immagini, video e archivi).
  • -P: mostra l'avanzamento e conserva i file parziali (--progress --partial).
  • --delete: elimina dalla destinazione ciò che non c'è più nell'origine.
  • --exclude / --include / --exclude-from: scelgono cosa saltare o includere.
  • -e "ssh -p 2222": comando di collegamento (porta o chiave diversa).
  • -u: non sovrascrive i file della destinazione più recenti di quelli dell'origine.
  • -c: confronta il contenuto (checksum) e non data e dimensione: più sicuro ma molto più lento.
  • -H / -A / -X: conserva hard link, ACL e attributi estesi.
  • --backup --backup-dir=DIR: invece di sovrascrivere o cancellare, sposta i vecchi file in una cartella.
  • --link-dest=DIR: backup incrementali con hard link.
  • --bwlimit=KB/s: limita la banda; --max-size / --min-size: filtra per dimensione.
  • --remove-source-files: cancella i file dell'origine dopo averli copiati (in pratica, un "sposta").
  • --rsync-path="sudo rsync": esegue rsync con sudo sul server remoto (richiede che sudo non chieda la password).

Attenzione a

  • La barra finale sull'origine: progetto/ copia il contenuto, progetto copia la cartella. Sbagliare significa ritrovarsi con una cartella in più (o con file sparsi) nella destinazione.
  • --delete è pericoloso: se origine e destinazione sono invertite, o l'origine è vuota o non montata, cancella dalla destinazione ciò che c'è. Prima di usarlo, controlla i percorsi con -n. Per una rete di sicurezza si può aggiungere --backup --backup-dir=..., che sposta i file invece di cancellarli.
  • Origine e destinazione nell'ordine giusto: l'origine viene prima. Il verso della copia non si capisce dal comando se non si legge con attenzione.
  • Non è un backup, da solo: una sincronizzazione con --delete copia fedelmente anche gli errori. Se cancelli un file per sbaglio e poi sincronizzi, sparisce anche dalla copia. Per un vero backup servono versioni nel tempo (--link-dest o --backup-dir) e una copia in un luogo diverso.
  • Permessi e proprietari: -a prova a conservarli, ma cambiare proprietario riesce solo a root sulla destinazione. Per copiare file di sistema o di un altro utente serve sudo (in locale, o sul server con --rsync-path).
  • File system senza permessi Unix: copiando su dischi FAT/exFAT o su alcune condivisioni di rete, -a genera errori su permessi e proprietari. Si usa -rltD (senza p, o, g), tenendo conto che FAT ha una risoluzione delle date di 2 secondi (--modify-window=2).
  • Gli asterischi e la shell: rsync -av progetto/* copia/ fa espandere l'asterisco alla shell (e salta i file nascosti). Meglio usare progetto/. Nei percorsi remoti con asterisco servono le virgolette.
  • Spazi nei nomi: nei percorsi remoti, con versioni vecchie di rsync, uno spazio nel nome va protetto due volte. Le versioni recenti (3.2.4 e successive) lo gestiscono meglio. Conviene evitare gli spazi nei nomi di file e cartelle.
  • File aperti e database: copiare con rsync i file di un database in funzione può produrre una copia incoerente. Meglio un'esportazione (ad esempio con mysqldump o pg_dump) e poi la sincronizzazione del file esportato.
  • Interruzioni: senza --partial un file trasferito a metà viene scartato e si ricomincia da capo. Con -P si riprende.
  • Collegamenti simbolici: con -a vengono copiati come collegamenti. Se vuoi copiare i file a cui puntano, usa -L.
  • Se rsync è lento: con milioni di file l'elenco iniziale richiede tempo e memoria. Per file già compressi -z aggiunge solo carico di lavoro.

Riepilogo

ComandoCosa fa
rsync -av origine/ destinazione/Copia il contenuto di una cartella, conservando i metadati
rsync -avn origine/ destinazione/Simula, senza modificare nulla
rsync -avz origine/ utente@host:percorso/Copia verso un server (con compressione)
rsync -avz utente@host:percorso/ destinazione/Scarica da un server
rsync -avP file utente@host:percorso/Mostra l'avanzamento e permette di riprendere
rsync -av --delete origine/ destinazione/Rende la destinazione identica all'origine
rsync -av --exclude='*.tmp' origine/ destinazione/Esclude file o cartelle
rsync -a --link-dest=precedente/ origine/ nuovo/Backup incrementale con hard link
rsync -e "ssh -p 2222" ...Usa una porta SSH diversa
rsync -avi ...Spiega il motivo di ogni trasferimento