Command Line - Linux

rsync: Sincronizzazione e Trasferimento file

rsync è l’abbreviazione di Remote Sync, ma la sua utilità va ben oltre la semplice sincronizzazione remota. Gestisce file, server, backup o pipeline di dati: è veloce, affidabile, flessibile e, soprattutto, “intelligente”.

La caratteristica che lo rende unico rispetto a strumenti analoghi come cp o scp è il suo algoritmo: invece di copiare l’intero file ogni volta, rsync identifica le sole porzioni modificate e trasferisce esclusivamente quelle garantendo trasferimenti più rapidi, con un minor consumo di banda e una gestione efficiente anche per file di grandi dimensioni.

Iniziamo a capire come funziona l’algoritmo di rsync che opera in quattro fasi fondamentali

  • Checksumming: il destinatario divide il file esistente in blocchi di dimensione fissa e calcola per ciascuno due checksum: un rolling checksum debole (Adler-32) e un checksum MD4 più forte
  • Invio dei checksum: questi valori vengono inviati alla sorgente
  • Ricerca delle differenze: la sorgente scansiona il proprio file cercando corrispondenze con i blocchi del destinatario. I blocchi identici vengono identificati; le porzioni differenti vengono marcate come “delta”
  • Trasferimento selettivo: solo i delta vengono trasmessi, assieme alle istruzioni su come ricostruire il file finale

Questo approccio riduce il traffico di rete in modo drastico in scenari di aggiornamento frequente: immaginiamo di sincronizzare un database da 10 GB con una modifica dell’1%, rsync trasferirà circa 100 MB invece di 10 GB.

Su quasi tutte le distribuzioni Linux, rsync è preinstallato o disponibile nei repository ufficiali. Qualora non lo fosse, l’installazione è molto semplice

# Debian / Ubuntu
sudo apt update && sudo apt install rsync

# Red Hat / CentOS / Fedora
sudo dnf install rsync

# macOS (tramite Homebrew)
brew install rsync

# Per verificare la versione installata
rsync --version

La versione 3.x introduce numerosi miglioramenti rispetto alla 2.x, tra cui supporto per file superiori a 2 GB, migliore gestione delle ACL e incrementi di prestazioni. È consigliabile utilizzare sempre l’ultima versione stabile disponibile.

Sintassi generale

La struttura del comando rsync è

rsync [OPZIONI] SORGENTE DESTINAZIONE

Dove SORGENTE e DESTINAZIONE possono essere

  • Un percorso locale: /home/utente/documenti/
  • Un percorso remoto via SSH: utente@server:/percorso/remoto/
  • Un modulo rsync daemon: rsync://server/modulo/

Iniziamo subito a chiarire una possibile fonte di confusione, la presenza o assenza dello slash finale sulla directory sorgente. Questo cambia il comportamento in modo significativo

# Copia la directory "foto" e il suo contenuto dentro "backup"
rsync -av /home/carlo/foto /backup/

# Copia solo il CONTENUTO di "foto" dentro "backup"
rsync -av /home/carlo/foto/ /backup/

Nel primo caso, il risultato sarà /backup/foto/img001.jpg. Nel secondo caso, il risultato sarà /backup/img001.jpg.

Le opzioni

rsync offre decine di opzioni. Di seguito le più importanti, raggruppate per categoria

Opzioni di modalità e verbosità

OpzioneForma lungaDescrizione
-v–verboseOutput dettagliato delle operazioni
-q–quietSopprime l’output (ideale per cron job)
-n–dry-runSimula l’esecuzione senza trasferire nulla
–progressMostra il progresso durante il trasferimento
–statsMostra statistiche dettagliate al termine
–info=FLAGSControllo granulare dell’output informativo

Opzioni di copia

OpzioneForma lungaDescrizione
-r–recursiveRicorsivo: include le sottodirectory
-a–archiveModalità archivio: equivale a -rlptgoD
-l–linksPreserva i symlink come symlink
-p–permsPreserva i permessi
-t–timesPreserva i timestamp di modifica
-g–groupPreserva il gruppo proprietario
-o–ownerPreserva il proprietario (richiede l’esecuzione come root)
-DPreserva device file e file speciali
-H–hard-linksPreserva gli hard link
-A–aclsPreserva gli ACL POSIX
-X–xattrsPreserva gli attributi estesi
-z–compressComprime i dati durante il trasferimento

L’opzione -a è probabilmente la più comune nei comandi rsync. Attiva automaticamente: -r (ricorsivo), -l (symlink), -p(permessi), -t (timestamp), -g (gruppo), -o (owner), -D (device files). È la scelta ideale per backup e sincronizzazioni complete.

Opzioni di sincronizzazione e controllo

OpzioneForma lungaDescrizione
–deleteElimina dalla destinazione i file non presenti nella sorgente
–delete-beforeElimina prima del trasferimento
–delete-afterElimina dopo il trasferimento
–delete-excludedElimina anche i file esclusi dalla destinazione
–ignore-existingNon sovrascrive file già presenti nella destinazione
-u–updateSalta file più recenti nella destinazione
-c–checksumUsa checksum invece dei timestamp per confrontare
–size-onlyConfronta solo per dimensione
-b–backupCrea backup dei file sovrascritti
–backup-dir=DIRSpecifica directory per i backup
–suffix=SUFFIXSuffisso per i file di backup (default: ~)

Opzioni di rete e performance

OpzioneForma lungaDescrizione
-e–rsh=COMMANDSpecifica la shell remota (es. SSH)
–bwlimit=KbpsLimita la banda utilizzata
–partialMantieni i file parzialmente trasferiti
–partial-dir=DIRDirectory per file parziali
–inplaceAggiorna il file in-place senza copia temporanea
–appendAggiunge dati a file esistenti
–timeout=SECTimeout I/O in secondi

Esempi pratici

Dopo aver visto le varie opzioni del comando rsync, analizziamo alcuni esempi di comandi.

rsync -av /home/carlo/documenti/ /media/usb/backup-documenti/

Copia il contenuto di documenti nella directory backup-documenti sul dispositivo USB, preservando tutti i metadati e mostrando ogni file copiato

rsync -avn --delete /home/carlo/documenti/ /media/usb/backup-documenti/

L’opzione -n (dry-run) è fondamentale: mostra esattamente cosa verrebbe fatto senza toccare nulla. Va usata sempre prima di operazioni critiche, specialmente quando si usa –delete

rsync -av --delete /home/carlo/documenti/ /media/usb/backup-documenti/

Con –delete, la destinazione diventa una copia identica della sorgente: i file rimossi dalla sorgente vengono eliminati anche dalla destinazione

rsync -av --progress /home/carlo/video/ /media/nas/video/

Utile per trasferimenti lunghi: mostra la percentuale di completamento, la velocità di trasferimento e il tempo rimanente per ogni file

rsync -av --stats /home/carlo/foto/ /backup/foto/

Al termine del trasferimento, –stats fornisce un riepilogo con numero di file trasferiti, byte totali, byte effettivamente inviati (grazie alla compressione delta), velocità media e tempo impiegato

# Da locale a remoto
rsync -avz /percorso/locale/ utente@server.esempio.com:/percorso/remoto/

# Da remoto a locale
rsync -avz utente@server.esempio.com:/percorso/remoto/ /percorso/locale/

Una delle feature più potenti di rsync è la capacità di operare su connessioni SSH, rendendo possibile sincronizzare dati tra macchine remote in modo sicuro. L’opzione -z aggiunge la compressione, particolarmente vantaggiosa su connessioni lente

rsync -avz -e "ssh -p 2222" /dati/ utente@server.esempio.com:/backup/dati/

Specifica una porta SSH non standard

rsync -avz -e "ssh -i ~/.ssh/chiave_privata -p 22" \
    /dati/ utente@server.esempio.com:/backup/dati/

Usa una chiave ssh per il trasferimento che rende molto più sicuro lo script

# Esclude una singola directory, es. tmp
rsync -av --exclude='tmp' /progetto/ /backup/progetto/

# Esclude più pattern
rsync -av \
    --exclude='*.log' \
    --exclude='*.tmp' \
    --exclude='.git' \
    --exclude='__pycache__' \
    /progetto/ /backup/progetto/

Esegue un backup selettivo escludendo un’intera directory “tmp” oppure una serie di directory o file con le estensioni specificate. Per scenari complessi, è pratico creare un file dedicato alle esclusioni

# Crea il file exclude-list.txt
cat > ~/exclude-list.txt << 'EOF'
*.log
*.tmp
*.cache
.git/
node_modules/
__pycache__/
.DS_Store
Thumbs.db
*.swp
/tmp/
EOF

# Usa il file
rsync -av --exclude-from='~/exclude-list.txt' /progetto/ /backup/progetto/

rsync applica le regole di filtro nell’ordine in cui compaiono, la prima regola che corrisponde viene applicata. Questo è fondamentale per costruire filtri precisi

# Copia solo i file .php e .html, escludendo tutto il resto
rsync -av \
    --include='*/' \
    --include='*.php' \
    --include='*.html' \
    --exclude='*' \
    /sito-web/ /backup/sito-web/

In questo esempio, sono incluse tutte le directory (*/) per permettere la navigazione ricorsiva, include i file .php e .html, esclude tutto il resto. L’ordine è fondamentale, invertirlo produce risultati completamente diversi

# Esclude /progetto/logs/ ma non /progetto/src/logs/
rsync -av --exclude='/logs/' /progetto/ /backup/progetto/

# Esclude qualsiasi directory "logs" a qualsiasi livello
rsync -av --exclude='logs/' /progetto/ /backup/progetto/

La barra iniziale nell’esclusione ancora il pattern alla radice della sorgente

rsync -av --backup --backup-dir=/backup/modificati-$(date +%Y%m%d) --delete /dati/ /backup/corrente/

Ad ogni esecuzione, i file modificati o eliminati vengono spostati in una directory con la data corrente. Si riesce quindi a mantenere una copia corrente sempre aggiornata più uno storico delle versioni precedenti

# Confronta sorgente e backup usando checksum (lento ma accurato)
rsync -avnc --delete /dati/ /backup/dati/

L’opzione -c (checksum) ignora timestamp e dimensioni, confrontando il contenuto effettivo dei file. Utile per verifiche periodiche dell’integrità

# Limita a 10 MB/s (il valore è in KB/s)
rsync -avz --bwlimit=10240 /dati/ utente@server.esempio.com:/backup/

Permette di gestire la banda utilizzata durante il trasferimento evitando, soprattutto su connessioni non veloci, di saturarla

# Trasferisce 4 elementi in parallelo
ls /sorgente/ | parallel -j4 \
    rsync -av /sorgente/{} utente@server.esempio.com:/destinazione/{}

Parallelizza i trasferimenti utilizzando parallel, molto utilizzato nel caso di directory con migliaia di file piccoli per ridurre il tempo di trasferimento

# Prima sincronizzazione: usa tar per l'invio iniziale
tar czf - /dati/ | ssh utente@server.esempio.com "tar xzf - -C /backup/"

# Aggiornamenti successivi: usa rsync per i delta
rsync -av --delete /dati/ utente@server.esempio.com:/backup/dati/

Un altro modo per gestire la sincronizzazione di directory con migliaia di file è combinarne l’utilizzo con tar con cui fare un trasferimento iniziale e poi con rsync gestire la sincronizzazione delle differenze

#!/bin/bash
# Sincronizza i dump giornalieri del database

DUMP_DIR="/var/backups/mysql"
REMOTE="server.esempio.com:/archivio/mysql"

# Genera dump
mysqldump --all-databases | gzip > "$DUMP_DIR/all-databases-$(date +%Y%m%d).sql.gz"

# Rimuovi dump più vecchi di 7 giorni localmente
find "$DUMP_DIR" -name "*.sql.gz" -mtime +7 -delete

# Sincronizza con il server di backup remoto
rsync -avz --delete \
    --stats \
    "$DUMP_DIR/" \
    "utente@$REMOTE/"

In questo piccolo script di esempio vengono sincronizzati i dump dei database su un server remoto, mantenendo i due archivi allineati