Ripristino di file system corrotti su VPS senza supporto tecnico: guida immediata Debian e Ubuntu
Qualche mese fa, di sabato mattina presto, mi ha chiamato il titolare di un'azienda del settore distribuzione ricambi, con un gestionale Laravel su un VPS Hetzner, perché il server non rispondeva più. Il pannello Hetzner Cloud mostrava la macchina in stato "running", ma la console VNC presentava un loop di riavvio: il kernel si avviava, tentava di montare il filesystem root ext4, falliva con EXT4-fs error: unable to read itable block, e riavviava. Il server era stato spento bruscamente il giorno prima per un'interruzione di corrente nel data center, e il filesystem non era sopravvissuto integro allo spegnimento non pulito.
La situazione era critica per due ragioni. Prima: il database MySQL dell'intero anno (ordini, fatture, listini, anagrafiche clienti e fornitori) viveva su quel filesystem. Seconda: il backup, come avrei scoperto poco dopo, non funzionava da settimane perché il cron job falliva silenziosamente con un errore di autenticazione sullo storage offsite che nessuno aveva notato. Alcune ore dopo, con rescue mode, una copia bit-per-bit del disco, e2fsck con backup superblock e un import selettivo dei dati, il gestionale era di nuovo operativo. In questo articolo ti racconto ogni passaggio della procedura, esteso ai tre filesystem che incontri davvero in produzione (ext4, XFS, Btrfs), perché la differenza tra recovery totale e perdita dati irreversibile sta nella sequenza di azioni nei primi trenta minuti e nella scelta dello strumento giusto per il filesystem giusto.
Stai cercando un Consulente Informatico esperto per gestire emergenze di disaster recovery sulla tua infrastruttura? Nel mio profilo professionale trovi l'esperienza concreta su rescue mode, ripristino filesystem e recupero dati su Hetzner, OVH, Contabo e Digital Ocean.
Come si riconosce un filesystem corrotto e perché non devi mai fare fsck su un disco montato?
Un filesystem corrotto si manifesta tipicamente con uno o più di questi sintomi: errori Input/output error quando provi a leggere o scrivere file, messaggi EXT4-fs error (o XFS (sda1): corruption detected) nel kernel log visibili con dmesg, il server che non riesce a bootare e cade in emergency mode, oppure file che appaiono vuoti o troncati senza ragione apparente. Le cause più comuni sono tre: spegnimento non pulito (power loss, kernel panic, hard reboot), hardware guasto (settori danneggiati sull'SSD/NVMe) e bug del kernel o del driver filesystem.
La regola fondamentale, che non ammette eccezioni, è: non eseguire mai una riparazione su un filesystem montato. Lo strumento di check (fsck per ext4, xfs_repair per XFS, btrfs check per Btrfs) modifica le strutture interne durante la riparazione; se il filesystem è montato e in uso, il kernel e il tool di repair scrivono contemporaneamente sulle stesse strutture, con risultato quasi certo di corruzione aggiuntiva. La regola vale per tutti e tre i filesystem: il manuale ufficiale di xfs_repair è esplicito nel richiedere che "the filesystem to be repaired must be unmounted, otherwise, the resulting filesystem may be inconsistent or corrupt".
Questo significa che per riparare il filesystem root (quello che contiene il sistema operativo e su cui il server sta girando) devi necessariamente avviare da un sistema alternativo. Su un VPS questo sistema alternativo è il rescue mode del provider.
Fase 1: rescue mode e l'immagine di sicurezza che ti salva il sabato mattina
Ogni provider serio offre una modalità rescue: Hetzner la attiva dal Cloud Console con un click, OVH dal pannello con boot in "Rescue", Digital Ocean dalla Recovery Console, Contabo via ticket di supporto. Il rescue mode avvia il VPS con un sistema Linux minimale caricato via rete (PXE), lasciando i dischi del server accessibili come device a blocchi non montati: è esattamente la condizione che ti serve per lavorare in sicurezza.
Il primo comando, una volta dentro il rescue, non è la riparazione. È un'immagine del disco. E qui c'è la prima correzione importante rispetto a come la maggior parte delle guide affronta il problema: se sospetti anche solo lontanamente che il disco sia fisicamente danneggiato, non usare dd per l'immagine, usa ddrescue.
La differenza è sostanziale. dd legge in sequenza dall'inizio alla fine: appena incontra un settore illeggibile o si blocca, oppure (peggio) continua a martellare lo stesso settore difettoso infliggendo ulteriore stress a un disco già morente. GNU ddrescue usa un algoritmo progettato per le superfici che cedono: come recita il manuale ufficiale, "tries to rescue the good parts first, scheduling reads inside bad (or slow) areas for later", copiando prima tutto il recuperabile e tornando solo dopo sui settori problematici, con il minor danno aggiuntivo possibile.
Il pezzo davvero non negoziabile è il mapfile. È un file di stato in cui ddrescue annota, blocco per blocco, cosa è stato letto, cosa è ancora da tentare e cosa è definitivamente perso. Ti permette di interrompere e riprendere esattamente dal punto giusto, e di fare più passate sui settori difficili senza ripartire da capo. La documentazione GNU è perentoria: "Always use a mapfile unless you know you won't need it".
# Disco di destinazione (un volume vuoto, o un file immagine) almeno
# grande quanto il sorgente. Mai scrivere sul disco che stai recuperando.
# Passata 1: copia veloce, salta i settori difficili e li annota nel mapfile
ddrescue -n /dev/sda /mnt/rescue/disk-image.img /mnt/rescue/mapfile.log
# Passata 2: accesso diretto (-d, bypassa la cache del kernel) e fino a 3 retry
# sui settori marcati come problematici nella passata precedente
ddrescue -d -r3 /dev/sda /mnt/rescue/disk-image.img /mnt/rescue/mapfile.logSe invece la diagnosi (SMART pulito, vedi sotto) conferma che il disco è sano e la corruzione è puramente logica da power loss, una copia bit-per-bit con dd è sufficiente e più semplice:
# Solo se il disco è hardware-sano: immagine bit-per-bit di sicurezza
dd if=/dev/sda of=/mnt/rescue/disk-image.img bs=4M status=progressQuesto passaggio è la rete di sicurezza dell'intera operazione. Se la riparazione incontra una situazione che non riesce a risolvere e decide di troncare dati o spostare file in
lost+found, l'immagine è l'unico modo per tornare allo stato pre-riparazione e tentare un approccio diverso. Sul disco che dovevo recuperare, poche decine di gigabyte occupati, l'immagine ha richiesto pochi minuti verso uno storage nella stessa località.
Fase 2: capire cosa è rotto prima di toccarlo
Con il disco non montato e l'immagine al sicuro, la diagnosi. La prima cosa da stabilire è quale filesystem stai guardando e se il disco è hardware-sano o sta morendo, perché le due risposte cambiano completamente la procedura.
# Tipo di filesystem di ogni partizione (ext4 / xfs / btrfs)
lsblk -f
blkid /dev/sda1
# Messaggi kernel relativi al disco e al filesystem
dmesg | grep -iE "error|ext4|xfs|btrfs|ata|nvme|sda"
# Stato di salute hardware del disco (SMART)
smartctl -H /dev/sda # verdetto sintetico PASSED/FAILED
smartctl -x /dev/sda # attributi estesi completiIl comando smartctl -H dà il verdetto sintetico di salute; smartctl -x (o -a) mostra gli attributi completi, come documentato nella pagina di smartctl(8). Gli attributi che contano davvero per capire se la corruzione è solo logica o se il disco sta cedendo fisicamente sono tre: Reallocated Sector Count (ID 5), Current Pending Sector Count (ID 197) e Offline Uncorrectable (ID 198). Se sono a zero, il disco è sano e la corruzione è logica, quindi riparabile in loco; se uno qualsiasi è non-zero e in crescita, il disco va sostituito e tu devi salvare i dati con ddrescue, non ripararli sul posto. Nel caso che ti sto raccontando, lo SMART era immacolato: corruzione logica da spegnimento non pulito, non hardware guasto.
A questo punto, in base al filesystem, si diramano tre procedure diverse.
ext4: e2fsck, journal replay e backup superblock
Su ext4 il check di sola lettura è e2fsck -n, che riporta cosa farebbe senza toccare nulla. Poi si ripara, seguendo un ordine preciso: prima con il journal, poi rimuovendo e ricreando il journal, infine, se il superblock primario è distrutto, da un backup superblock.
# Diagnosi non distruttiva: cosa è rotto, senza scrivere
e2fsck -n /dev/sda1
# Riparazione standard con journal replay
e2fsck -fvy /dev/sda1
# -f forza il check anche se il fs sembra pulito, -v verbose, -y "sì" a tutto
# Se il journal è corrotto: rimuoverlo, richeckare, ricrearlo
tune2fs -O ^has_journal /dev/sda1
e2fsck -fvy /dev/sda1
tune2fs -O has_journal /dev/sda1
# Se "Bad magic number in super-block": usare un backup superblock
dumpe2fs /dev/sda1 | grep -i superblock # elenca i backup, es. 32768, 98304...
e2fsck -b 32768 -fvy /dev/sda1La corruzione da power loss su ext4 con journal è quasi sempre recuperabile, perché il journal contiene esattamente le informazioni necessarie per riportare il filesystem a uno stato consistente. Nel caso reale, il primo tentativo (e2fsck -fvy) è bastato: journal replayato, una cinquantina di inode corretti, una dozzina di file spostati in lost+found/, filesystem di nuovo consistente.
XFS: dimentica fsck, esiste solo xfs_repair
Qui sta l'errore che vedo fare più spesso quando una PMI eredita un VPS con root su XFS (lo standard di default su molte derivate enterprise) e prova ad applicare le ricette di ext4. Su XFS non esiste un fsck funzionante. Il binario fsck.xfs esiste solo per compatibilità con la sequenza di boot, ma non fa nulla: esce immediatamente con successo. La verifica e la riparazione di XFS sono affidate esclusivamente a xfs_repair, e il design del filesystem è diverso: XFS si affida al replay del proprio log al mount per gestire le scritture interrotte, quindi nella stragrande maggioranza dei power loss il rimedio corretto è semplicemente montare e smontare il filesystem una volta per far replayare il log, non lanciare subito il repair.
# Scansione di sola lettura: cosa riparerebbe, senza modificare nulla
xfs_repair -n /dev/sda1
# Riparazione effettiva (filesystem SMONTATO, obbligatorio)
xfs_repair /dev/sda1Il flag -n su xfs_repair "should not modify the filesystem but should only scan the filesystem and indicate what repairs would have been made": è il primo comando da dare, sempre. Se invece il log è "sporco" e non può essere replayato (tipicamente quando provi a montarlo su un kernel di architettura diversa, o dopo un crash particolarmente brutto), xfs_repair rifiuta di procedere e suggerisce -L. Questo è il punto più pericoloso dell'intera procedura XFS, e il manuale non gira intorno al rischio:
Il flag
-L"forces xfs_repair to zero the log even if it is dirty (contains metadata changes). When using this option the filesystem will likely appear to be corrupt, and can cause the loss of user files and/or data."
Tradotto in pratica: xfs_repair -L azzera il log buttando via le scritture non ancora committate. È un'opzione di ultima istanza, da usare solo dopo aver fatto la disk image con ddrescue e solo se non hai alternative, mai come primo tentativo perché te lo suggerisce un messaggio frettoloso. La sequenza corretta è: prova il mount/umount per il replay del log, poi xfs_repair -n, poi xfs_repair, e solo all'estremo xfs_repair -L con l'immagine già al sicuro.
Btrfs: btrfs check come ultima spiaggia, scrub come prima linea
Btrfs ribalta la filosofia. Avendo i checksum su dati e metadati, la sua difesa primaria non è un repair offline ma lo scrub online: una passata che rilegge tutto il filesystem montato, verifica ogni checksum e, se esiste ridondanza (profilo RAID1 o DUP), ripara automaticamente copiando dalla replica sana.
# Scrub online su filesystem MONTATO: verifica tutti i checksum
btrfs scrub start -B /mnt # -B = foreground, con statistiche finali
btrfs scrub status /mnt # avanzamento e contatori di erroreIl limite va capito bene, perché su un VPS economico con un solo disco è la norma: su un profilo single (nessuna ridondanza) lo scrub può rilevare la corruzione tramite i checksum ma non ripararla, perché non esistono copie buone da cui attingere. La documentazione ufficiale btrfs-scrub lo dice senza ambiguità: lo scrub "can only repair filesystem damage by copying from other known good replicas". Su disco singolo, lo scrub ti dice esattamente quali file sono danneggiati, e quelli li ripristini dal backup.
Per le corruzioni strutturali profonde c'è btrfs check, ma il suo flag --repair è dichiaratamente l'opzione più rischiosa di tutto l'ecosistema filesystem Linux. La documentazione btrfs-check avverte:
"Do not use --repair unless you are advised to do so by a developer or an experienced user, and then only after having accepted that no fsck successfully repair all types of filesystem corruption."
Tanto che lo strumento impone un'attesa di 10 secondi prima di partire, per darti il tempo di ripensarci. La regola operativa su Btrfs è quindi: btrfs check in sola lettura per diagnosticare, scrub per riparare dove c'è ridondanza, e per il resto il backup, riservando btrfs check --repair ai casi in cui un developer del progetto ti ha detto esplicitamente di provarlo, sempre su una disk image, mai sul disco originale.
# Diagnosi in sola lettura (filesystem SMONTATO)
btrfs check /dev/sda1
# Recupero dei dati leggibili verso un'altra destinazione, senza riparare nulla
# (utile quando il fs non monta più ma vuoi salvare i file recuperabili)
btrfs restore /dev/sda1 /mnt/recovered/Fase 3: verifica dei dati e ripristino del servizio
Riparato il filesystem, lo monto in sola lettura quando possibile e verifico l'integrità dei dati critici prima di rimettere in produzione qualsiasi cosa:
# Montare il filesystem riparato (read-only finché non sono certo)
mount -o ro /dev/sda1 /mnt
# Verificare che i file critici esistano e abbiano dimensione sensata
ls -la /mnt/var/www/html/artisan # codice applicativo Laravel
ls -la /mnt/var/lib/mysql/ibdata1 # tablespace InnoDB
ls -la /mnt/etc/nginx/nginx.conf # config Nginx
# Cosa è finito in lost+found (ext4): tipo di ogni file orfano
file /mnt/lost+found/*I file finiti in lost+found nel caso reale erano tutti file temporanei di PHP e log di Nginx, nessun file critico. Il database MySQL (i file .ibd delle tabelle InnoDB, il tablespace, i binary log) era integro. Ho riavviato in modalità normale, verificato che MySQL si avviasse senza errori, e testato il gestionale navigando le pagine principali e controllando la consistenza dei dati.
Quando invece e2fsck produce centinaia di file orfani con nome perso (rinominati col numero di inode, es. #12345), debugfs permette di risalire al nome e alla directory originali tramite le informazioni dell'inode, come documentato nel manuale di debugfs. Ma nella pratica vale una regola che non smetto di ripetere: se hai un backup funzionante, ripristinare da backup è quasi sempre più veloce e più sicuro che ricostruire da lost+found. Il che ci porta al punto che pesa più di ogni comando di questo articolo.
Perché la riparazione del filesystem non è (mai) un sostituto del backup
Ho aperto questo articolo con un dettaglio che non era un caso di colore: il backup non funzionava da settimane, e nessuno lo sapeva. Questo è lo scenario reale, non l'eccezione. Un backup che fallisce silenziosamente è indistinguibile da un backup che non esiste, e te ne accorgi esattamente nel momento peggiore: quando ti serve. Tutte le procedure di repair che hai letto fin qui, da e2fsck a xfs_repair a btrfs check, sono interventi di ultima istanza che provi perché il backup non c'era o non bastava. Una riparazione riuscita è fortuna ingegnerizzata; un backup verificato è la cosa che rende quella fortuna superflua.
La differenza sta nella parola verificato. Un job di backup che gira non è un backup: è un backup solo quando hai dimostrato di poter fare il restore. Nella mia pratica un backup non testato non conta, e la verifica deve essere automatica e periodica, non un controllo manuale che nessuno fa più dopo la prima settimana. Ho documentato l'approccio operativo, inclusa la verifica periodica dell'integrità che avrebbe intercettato la chiave SSH scaduta prima del disastro, nell'articolo dedicato alle strategie di backup per VPS unmanaged, e l'ho inquadrato nel più ampio piano di disaster recovery per la continuità operativa di una PMI, dove lo scenario "filesystem corrotto" è uno dei rischi da coprire esplicitamente con RPO e RTO realistici.
Come si previene la corruzione del filesystem su un VPS e come la si scopre prima del disastro?
La prevenzione poggia su due gambe: ridurre la probabilità che il filesystem si corrompa, e accorgersi che il disco sta cedendo prima che ti pianti il server. Sul primo fronte, ti assicuri che il filesystem usi il journaling (ext4 lo ha di default; lo verifichi con tune2fs -l /dev/sda1 | grep has_journal), perché il journal replaya le operazioni in sospeso al riavvio e ti evita gran parte dei fsck post-crash. Su XFS e Btrfs il meccanismo è intrinseco (log interno e copy-on-write con checksum rispettivamente). Su un'infrastruttura che gestisci tu, vale anche disciplinare gli spegnimenti: l'hard reboot dal pannello è l'ultima opzione, non la prima.
Sul secondo fronte, quello che fa la vera differenza, c'è il monitoring SMART proattivo. Non basta lanciare smartctl quando il server è già morto: vuoi che il disco ti avvisi mentre è ancora vivo. Due strumenti:
# Self-test breve (1-2 minuti) e completo (può richiedere ore), poi il log
smartctl -t short /dev/sda
smartctl -t long /dev/sda
smartctl -l selftest /dev/sdaIl flag -t short avvia un test di superficie rapido che intercetta i difetti più comuni, -t long fa una scansione completa; i risultati finiscono nel self-test log leggibile con -l selftest. Ma il pezzo che trasforma il monitoring da reattivo a proattivo è il demone smartd: gira in background, interroga i dischi a intervalli regolari (30 minuti di default) e ti manda un'email appena un attributo critico si muove. La configurazione minima che applico mette sotto sorveglianza proprio gli attributi che predicono i guasti, con la direttiva -a (che include health, error log e i contatori di settori) più gli alert sugli incrementi:
# /etc/smartd.conf - alert solo sugli INCREMENTI dei settori critici
/dev/sda -a -m [email protected] -C 197+ -U 198+ -R 5! -s (S/../.././02|L/../../6/03)Qui -C 197+ e -U 198+ avvisano solo quando i pending sector e gli offline uncorrectable aumentano (così non ricevi la stessa email ogni giorno per un valore fermo), -R 5! tratta come critico ogni nuovo settore riallocato, e -s pianifica un self-test breve quotidiano e uno lungo settimanale. È la differenza tra scoprire il problema con settimane di anticipo e scoprirlo alle sette di un sabato mattina.
Se gestisci un VPS con dati di produzione e non hai mai testato cosa succede quando il filesystem si corrompe, e soprattutto se il monitoring SMART non ti scriverebbe un'email prima del guasto, stai operando senza rete di sicurezza. Il rescue mode, ddrescue per l'immagine, lo strumento di repair giusto per il tuo filesystem e un backup che hai effettivamente ripristinato almeno una volta sono cose che devi conoscere e avere pronte prima che servano, non durante il panico. Se vuoi un audit della resilienza della tua infrastruttura, o se ti trovi adesso con un VPS che non boota e un filesystem corrotto, contattami per una consulenza diretta: l'intervento più costoso è quello che arriva tardi, e la distanza tra un sabato mattina spiacevole e un lunedì col business fermo e i dati irrecuperabili sta tutta nelle scelte delle prime ore.