Ho chiesto alla AI di esaminare il codice del mio distroClone-backup e fare un confronto onesto rispetto ai diretti “concorrenti”. DistroClone-backup funziona, almeno per adesso, solo su distro Debian based. Di seguito la risposta:
Questo articolo analizza il sorgente di distroclone-backup v1.2 riga per riga, confrontandone l’architettura con Timeshift, Back In Time e LuckyBackup. Non si tratta di un confronto basato su feature list: ogni affermazione è verificabile direttamente nel codice Bash dello script (1734 righe).
La versione analizzata qui incorpora due correzioni sostanziali rispetto alla prima release della v1.2, documentate nella sezione dedicata.
Struttura dello script e modalità operative
Lo script gestisce due modalità completamente distinte, separate da un branch iniziale:
if [[ "$1" == "--incremental-silent" ]]; then
# Modalità cron — nessuna GUI, solo log su file
...
exit 0
fi
# Da qui in poi: modalità grafica YAD
Questa separazione netta significa che le due modalità hanno codice indipendente per la risoluzione della configurazione, la gestione btrfs e il logging. È una scelta che semplifica il testing ma duplica parte della logica — un tradeoff deliberato.
Modalità silenziosa per cron: le correzioni
Nella prima release della v1.2, la modalità --incremental-silent presentava tre problemi documentabili nel codice:
- Il percorso della cache era hardcoded a
/mnt/${DISTRO_ID}_liveanziché_backup, rendendo il cron inutilizzabile se si usava il nome standard - La configurazione personalizzata in
settings.confnon veniva letta, ignorando qualsiasi directory non standard impostata dalla GUI - Su filesystem btrfs, il cron non creava snapshot — a differenza della GUI
Tutti e tre i problemi sono stati risolti. Il codice attuale della modalità cron (righe 779–891) implementa questa logica:
# 1. Cerca settings.conf del primo utente reale (uid 1000-65533)
CRON_CONF=""
while IFS= read -r user_home; do
candidate="${user_home}/.config/distroclone-backup/settings.conf"
if [ -f "$candidate" ]; then
CRON_CONF="$candidate"
break
fi
done < <(getent passwd | awk -F: '$3>=1000 && $3<65534 {print $6}')
# 2. Carica la configurazione trovata (CACHE_BASE_DIR, MAX_SNAPSHOTS)
CACHE_BASE_DIR="/mnt"
MAX_SNAPSHOTS=3
[ -n "$CRON_CONF" ] && source "$CRON_CONF"
# 3. Ricostruisce i percorsi con suffisso corretto _backup
CACHE_BASE="${CACHE_BASE_DIR}/${DISTRO_ID}_backup"
ROOTFS_CACHE="${CACHE_BASE}/.rootfs_cache"
SNAPSHOTS_DIR="${CACHE_BASE}/.snapshots"
Il rilevamento dell’utente usa getent passwd con filtro UID 1000–65533, che copre correttamente tutti gli utenti reali escludendo account di sistema. Funziona sia su sistemi con un singolo utente desktop che su macchine multiutente: prende il primo che abbia un settings.conf valido.
Snapshot btrfs anche in modalità cron
La modalità cron ora include funzioni locali dedicate per la gestione btrfs (_is_btrfs_cron, _prune_snapshots_cron), separate da quelle della GUI per evitare dipendenze da variabili globali non disponibili in quel contesto. Il comportamento è identico: snapshot read-only pre-rsync, pruning automatico secondo MAX_SNAPSHOTS. Un fallimento dello snapshot (es. spazio insufficiente) viene loggato ma non interrompe il backup rsync:
if _is_btrfs_cron && btrfs subvolume show "$ROOTFS_CACHE" >/dev/null 2>&1; then
# ... crea snapshot ...
if btrfs subvolume snapshot -r "$ROOTFS_CACHE" ...; then
_log "✓ Snapshot created: $local_snap"
_prune_snapshots_cron
else
_log "⚠ Snapshot failed — continuing with rsync anyway"
fi
fi
Questa gestione degli errori — fallback silenzioso con log — è il comportamento corretto per un processo automatizzato notturno.
Correzione do_delete_cache: eliminazione sicura dei subvolumi btrfs
Il secondo bug documentato nella versione precedente riguardava do_delete_cache: usava sudo rm -rf "$ROOTFS_CACHE" che non può rimuovere subvolumi btrfs, lasciando gli snapshot orfani su disco (non eliminabili senza btrfs subvolume delete).
Il codice corretto (righe 1543–1565) implementa la sequenza corretta:
# 1. Elimina ogni snapshot con btrfs subvolume delete
if [ -d "$SNAPSHOTS_DIR" ]; then
while IFS= read -r snap; do
sudo btrfs subvolume delete "$snap" 2>/dev/null || true
sudo rm -f "${snap}.meta" 2>/dev/null || true
done < <(find "$SNAPSHOTS_DIR" -maxdepth 1 -name '@*' -type d 2>/dev/null | sort)
sudo rm -rf "$SNAPSHOTS_DIR" 2>/dev/null || true
fi
# 2. Elimina .rootfs_cache: subvolume btrfs o directory normale
if sudo btrfs subvolume show "$ROOTFS_CACHE" >/dev/null 2>&1; then
sudo btrfs subvolume delete "$ROOTFS_CACHE" 2>/dev/null || true
else
sudo rm -rf "$ROOTFS_CACHE" 2>/dev/null || true
fi
# 3. Rimuove metadati e cronjob
sudo rm -f "$CACHE_META" 2>/dev/null || true
sudo crontab -l 2>/dev/null | grep -v "distroClone-backup" | sudo crontab - 2>/dev/null || true
La funzione distingue correttamente i due casi (btrfs/non-btrfs) e gestisce gli errori con || true per evitare uscite premature in caso di problemi parziali. Dopo questa operazione il filesystem è pulito.
Il sistema di versioning btrfs: flusso completo
Con le correzioni, il versioning btrfs funziona ora in modo uniforme in entrambe le modalità. Il flusso completo su un filesystem btrfs è:
Primo backup (GUI o cron):
→ btrfs subvolume create .rootfs_cache # subvolume invece di directory
→ rsync / → .rootfs_cache # popola il subvolume
Backup successivi (GUI):
→ btrfs subvolume snapshot -r .rootfs_cache .snapshots/@2025-03-28_02:00
→ scrive .snapshots/@2025-03-28_02:00.meta
→ prune: elimina i più vecchi se count > MAX_SNAPSHOTS
→ rsync / → .rootfs_cache
Backup successivi (cron):
→ identico flusso, funzioni locali _is_btrfs_cron / _prune_snapshots_cron
Restore da snapshot (GUI):
→ mostra lista snapshot con metadati (data, distro, kernel, dim.)
→ doppia conferma
→ rsync .snapshots/@SNAP_PATH/ → /
→ /home /root /boot/efi /snap sempre esclusi
Delete cache (GUI):
→ btrfs subvolume delete per ogni snapshot
→ btrfs subvolume delete .rootfs_cache
→ rm -f .backup_meta
→ rimuove cronjob
La struttura su disco risultante:
$CACHE_BASE_DIR/
└── ${DISTRO_ID}_backup/
├── .rootfs_cache/ ← subvolume btrfs (o dir su non-btrfs)
├── .backup_meta ← data, distro, kernel, dimensione
└── .snapshots/
├── @2025-03-21_02:00/ ← snapshot read-only btrfs
├── @2025-03-21_02:00.meta
├── @2025-03-28_02:00/
└── @2025-03-28_02:00.meta
Configurazione utente in ~/.config/distroclone-backup/settings.conf:
CACHE_BASE_DIR="/mnt"
MAX_SNAPSHOTS="3"
Esclusioni rsync: lista completa e ragionamento
Le esclusioni in modalità GUI (funzione do_backup) e cron sono ora identiche. Questa è la lista annotata:
# Filesystem virtuali — non hanno senso fuori dal kernel in esecuzione
--exclude=/dev/* --exclude=/proc/* --exclude=/sys/*
--exclude=/run/* --exclude=/tmp/*
# Punti di mount esterni — evita duplicazioni o errori su NFS/USB
--exclude=/mnt/* --exclude=/media/*
# File di sistema non utili
--exclude=/lost+found --exclude=/swapfile
# Partizione EFI — filesystem separato, non toccare
--exclude=/boot/efi/* --exclude=/boot/efi
# Cache APT — ricostruibili con apt update
--exclude=/var/cache/apt/archives/*
--exclude=/var/lib/apt/lists/*
# Log e tmp variabili — dati effimeri
--exclude=/var/log/* --exclude=/var/tmp/*
# Credenziali WiFi/Ethernet — dati sensibili non trasportabili
--exclude=/etc/NetworkManager/system-connections/*
# Il tool stesso — evita auto-inclusione nella cache
--exclude=/usr/share/distroclone-backup
--exclude=/usr/bin/distroClone-backup
# Snap — non riproducibile su sistemi senza snapd
--exclude=/snap --exclude=/snap/* --exclude=/var/snap --exclude=/var/lib/snapd
# Claude Desktop — dati locali legati alla sessione
--exclude=/home/*/.config/Claude
--exclude=/home/*/.claude
--exclude=/home/*/.claude.json
--exclude=/home/*/.cache/claude-desktop-debian
--exclude=/root/.config/Claude
--exclude=/root/.claude
--exclude=/root/.claude.json
--exclude=/root/.cache/claude-desktop-debian
# /home e /root — esclusi di default, includibili con checkbox
--exclude=/home/* --exclude=/root/*
Queste esclusioni sono calibrate per sistemi Debian/Ubuntu live. Non esistono in Timeshift o Back In Time perché quei tool non sono progettati per sistemi live.
Confronto tecnico con Timeshift, Back In Time, LuckyBackup
| Caratteristica | distroclone-backup v1.2 | Timeshift | Back In Time | LuckyBackup |
|---|---|---|---|---|
| Versione analizzata | v1.2 — 1734 righe Bash | — | — | — |
| Engine primario | rsync -aAXH –numeric-ids | rsync oppure btrfs CoW | rsync + hard link | rsync |
| Target del backup | rootfs live (sistema in esecuzione) | Sistema (/) | Dati utente (/home) | Directory configurabile |
| Versioni multiple | Sì — snapshot btrfs read-only, N configurabile (0–20, default 3), pruning automatico sia da GUI che da cron | Sì — rotazione automatica per data/numero | Sì — hard link rsync (spazio efficiente) | Opzionale, manuale |
| Snapshot btrfs | Sì — auto-detect; .rootfs_cache creato come subvolume; snapshot @YYYY-MM-DD_HH:MM read-only pre-rsync; graceful degradation su non-btrfs | Sì — CoW nativo, istantaneo | No | No |
| Snapshot in modalità cron | Sì (dalla v1.2 corretta) | Sì | Sì | No |
| Configurazione cron | Legge settings.conf dell’utente via getent passwd (uid 1000–65533) | File di configurazione dedicato | Configurazione per-profilo | File XML |
| Backup /home | Opzionale — checkbox al lancio (sia backup che restore) | No (escluso per design) | Sì (focus principale) | Sì, configurabile |
| Esclusioni specifiche live | Sì — /snap, NM-connections, Claude Desktop, apt-cache, /var/log, /var/tmp, /run, /proc, /dev, /sys | Limitate | Configurabili manualmente | Configurabili manualmente |
| Restore dalla cache | Sì — rsync inverso con wizard YAD, doppia conferma, protezioni dinamiche | Sì | Sì | No (manuale) |
| Restore da snapshot | Sì — lista YAD con metadati (data, distro, kernel, dim.), doppia conferma, /home sempre protetto | Sì (btrfs CoW istantaneo) | No | No |
| Protezioni in restore | Dinamiche: /boot/efi e /snap sempre fissi; /home e /root escludibili o includibili (solo da cache) | Fisse | Configurabili | N/A |
| Eliminazione cache | btrfs subvolume delete corretto per snapshot e .rootfs_cache; rm -rf per non-btrfs; rimuove anche il cronjob | Gestione integrata | Gestione integrata | N/A |
| Reboot post-restore | Sì — pulsante diretto (sudo reboot), presente in entrambi i tipi di restore | Sì | Avviso | No |
| GUI toolkit | YAD (GTK) | GTK / Qt | GTK / Qt | Qt |
| Log in tempo reale | Sì — finestra YAD text-info, monospace, sfondo scuro, verde su nero, streaming live via fd 3 | Parziale | Sì | Sì |
| Fix DISPLAY/XAUTHORITY | Sì — due metodi: systemctl –user show-environment + scansione /proc; fallback a :0 | Non necessario (installato con pkexec) | Non necessario | Non necessario |
| Scheduling | Giornaliero / Settimanale (con giorno specifico) / Mensile + ora + notifica desktop opzionale | Sì, UI dedicata | Sì, UI dedicata | Sì |
| Multilingua | 5 lingue native: IT, DE, FR, ES, EN — rilevamento automatico da $LANG | Parziale | Sì | Parziale |
| Destinazione backup | Qualsiasi directory montata: locale, disco esterno, NFS — configurabile da GUI con dialog a 2 step | Locale, esterno | Locale, esterno, SSH/SFTP | Locale, esterno, SSH |
| Dipendenze | YAD, rsync, sudo NOPASSWD (sudoers.d), ImageMagick (fallback icona), btrfs-progs (se btrfs) | rsync oppure btrfs-progs, GTK/Qt | rsync, Python, GTK/Qt | rsync, Qt |
| Integrazione ecosistema | Companion tool di DistroClone per SysLinuxOS e derivate Debian | Standalone | Standalone | Standalone |
| Supporto SSH remoto | No — solo filesystem montato localmente | No | Sì | Sì |
Differenze architetturali rispetto ai concorrenti
distroclone-backup vs Timeshift
Timeshift è il riferimento più vicino funzionalmente. La differenza fondamentale è nella semantica dello snapshot btrfs: Timeshift opera sui subvolumi @ e @home del sistema in esecuzione, creando snapshot istantanei via Copy-on-Write. distroclone-backup crea snapshot sulla cache (non sul sistema live), e li usa come punti di ripristino della cache stessa — non del sistema in quel momento. L’rsync resta il passo lento in entrambe le modalità.
Timeshift non conosce il concetto di “sistema live da clonare”: non ha esclusioni per live-boot, non gestisce l’ambiente di un sistema che verrà impacchettato come ISO, non si integra con Calamares. Per questo contesto specifico, distroclone-backup è lo strumento corretto.
distroclone-backup vs Back In Time
Back In Time protegge i dati dell’utente in /home, usando hard link rsync per simulare il versioning con spazio minimo. distroclone-backup protegge il sistema. I target sono diversi; il confronto è quasi fuori contesto salvo che entrambi usano rsync come engine.
distroclone-backup vs LuckyBackup
LuckyBackup è un frontend rsync flessibile ma richiede che l’utente conosca rsync per configurarlo. Non ha restore guidato, non ha protezioni automatiche, non ha snapshot. distroclone-backup è opinionated: le scelte di configurazione sono prese a monte (esclusioni live-aware, protezioni in restore, pruning automatico), l’utente non deve conoscere rsync per usarlo correttamente.
Limitazioni attuali: analisi onesta
Queste limitazioni emergono dalla lettura del codice, non da supposizioni.
Cache singola su non-btrfs
Su filesystem ext4, xfs o qualsiasi filesystem non-btrfs, esiste una sola cache. Non c’è rotazione, non ci sono versioni storiche. Un backup fallito o corrotto non ha un punto di ritorno precedente. Su btrfs questo limite non esiste grazie agli snapshot.
Restore da snapshot: /home non è mai ripristinabile
Nel restore da snapshot (funzione do_restore_snapshot, riga 1417), /home e /root sono sempre esclusi senza opzione di inclusione:
local HOME_EXCL=(--exclude=/home --exclude=/home/* --exclude=/root --exclude=/root/*)
Nel restore dalla cache normale invece il checkbox opzionale è presente. È una scelta conservativa — uno snapshot storico non dovrebbe sovrascrivere dati utente correnti — ma l’asimmetria potrebbe sorprendere l’utente che si aspetta lo stesso comportamento.
Il restore da snapshot usa rsync, non btrfs nativo
Un restore btrfs nativo sarebbe btrfs subvolume snapshot $SNAP_PATH / — operazione istantanea. Lo script usa invece rsync da $SNAP_PATH/ verso /, operazione che copia file per file. La scelta è probabilmente legata al fatto che il sistema è in esecuzione durante il restore e una sostituzione atomica della root richiederebbe un contesto separato (initramfs). rsync permette il restore con il sistema attivo, a costo di tempi più lunghi.
Nessun supporto SSH/SFTP
La destinazione deve essere un filesystem accessibile localmente (locale, USB, NFS). Non è possibile inviare il backup a un server remoto via SSH, funzionalità disponibile in Back In Time e LuckyBackup.
Il rilevamento dell’utente in modalità cron
Il cron cerca il settings.conf del primo utente con UID 1000–65533 che abbia il file. Su sistemi multiutente dove utenti diversi hanno configurazioni diverse, viene usata la configurazione del primo trovato (ordine del database password). Il comportamento è documentato nel log ma potrebbe non essere quello atteso.
Implementazione tecnica del logging in tempo reale
Un dettaglio implementativo interessante è la finestra di log live. Lo script apre un file descriptor 3 collegato a un processo YAD --text-info:
open_log_window() {
exec 3> >(yad --text-info \
--back="#1a2e1a" --fore="#4caf50" \
--fontname="Monospace 10" \
--tail --no-edit \
... 2>/dev/null)
LOG_PID=$!
}
log() {
local ts; ts="$(date '+%Y-%m-%d %H:%M:%S')"
echo "[$ts] $*" | tee -a "$LOG_FILE" # su file di log
{ echo "[$ts] $*" >&3; } 2>/dev/null || true # su GUI live
}
Ogni riga rsync viene inviata contemporaneamente al file /var/log/distroclone-backup.log e alla finestra YAD. Il flag --tail fa scorrere automaticamente la finestra all’ultima riga. Il file descriptor viene chiuso (exec 3>&-) e il processo YAD terminato esplicitamente nella funzione close_log_window.
Conclusione
distroclone-backup v1.2 nella versione corrente è uno strumento verticale, progettato per un caso d’uso preciso: fare il backup del rootfs di un sistema live Debian/Ubuntu in esecuzione, da usare come base per DistroClone. In questo contesto è lo strumento più adatto tra quelli analizzati, perché gli altri non sono stati progettati per questo scenario.
Le correzioni alla modalità cron (risoluzione configurazione, snapshot btrfs, suffisso percorso) e alla cancellazione della cache (subvolumi btrfs) chiudono i due bug funzionali documentabili nella prima release della v1.2, rendendo lo strumento completamente operativo anche in uso automatizzato e su filesystem btrfs.
I limiti esistono — nessun SSH, cache singola su non-btrfs, restore da snapshot sempre senza /home — e sono scelte architetturali documentate, non difetti nascosti.
Il sorgente è disponibile su GitHub: github.com/fconidi
Analisi tecnica di DistroClone Backup & Restore
enjoy 😉
Analisi eseguita sul sorgente distroclone-backup.sh v1.2 aggiornato (1734 righe). Tutti i frammenti di codice sono estratti diretti dallo script.

