<aaronc@pobox.com>
rm * ~
. E, troppo tardi, notate lo spazio di troppo in quel
comando. Avete appena cancellato la vostra magnum opus!
Ma ecco l'aiuto. Questo documento vi presenta una discussione su come
recuperare i file cancellati da un filesystem Second Extended. Così,
forse, potrete fare uscire quel programma...
Questo mini-howto è un tentativo di fornire suggerimenti su come recuperare file cancellati da un filesystem ext2. Contiene anche una breve discussione su come evitare a priori di cancellare dei file.
La mia intenzione è che sia utile sicuramente per le persone che abbiano
appena avuto, diciamo, un piccolo incidente con rm
;, ma spero che venga
letto comunque. Non si sa mai, un giorno queste informazioni vi potrebbero
salvare la pelle.
Il testo assume una conoscenza di base dei filesystem UNIX in generale, ma spero che sia accessibile alla maggior parte degli utenti Linux. Se siete dei veri principianti, ho paura che il recupero di file sotto Linux richieda una certa conoscenza tecnica, almeno al momento.
Non potrete recuperare dei file cancellati da un filesystem ext2 senza avere
almeno accesso in lettura al dispositivo fisico in cui il file si trovava. In
generale, questo significa che dovete essere root. Vi serve anche debugfs
dal pacchetto e2fsprogs
, che dovrebbe essere stato installato dalla
distribuzione che avete.
Perché ho scritto questo documento? Più che altro è nato
dalla mia esperienza con un particolarmente stupido e disastroso
comando rm -r
da root. Ho cancellato circa 97 file JPEG che mi servivano e non avrei
potuto quasi sicuramente recuperare da altre fonti. Usando alcuni suggerimenti
utili (vedere la sezione
Ringraziamenti e bibliografia) e molta testardaggine, ho recuperato 91 file integri. Sono
riuscito a recuperare almeno delle parti di 5 dei restanti (abbastanza per
vedere quale era la figura). Solo uno è andato perso del tutto,
e anche di
questo sono quasi sicuro che non ne ho persi più di 1024 byte (anche
se sfortunatamente erano all'inizio del file: e non so niente del formato dei
file JFIF e ho fatto tutto quello che potevo).
Discuterò più avanti quale percentuale di recupero ci si può aspettare per i file cancellati.
Le varie revisioni pubbliche di questo documento (e le loro date di pubblicazione) sono le seguenti:
Quali modifiche sono state fatte in questa versione? Prima di tutto, ho corretto il "thinko" nell'esempio del recupero file. Grazie a tutti quelli che mi hanno scritto: spero di avere imparato ad essere più attento quando scrivo delle interazioni con i programmi.
Seconda cosa, ho riscritto la discussione sullo schema del filesystem UNIX, in modo che sia, spero, più comprensibile. Non ne ero molto contento all'inizio, e i commenti di alcune persone mi hanno indicato che non era chiaro.
Terzo, ho rimosso il .tar.gz uuencodato di fsgrab
che era nel mezzo del
file. Il programma è adesso disponibile dal
mio sito web
e presto dovrebbe arrivare su
Sunsite
(e sui mirror).
Quarta cosa, il documento è stato tradotto nel linguaggio SGML usato dal Linux Documentation Project. Questo linguaggio può essere facilmente convertito in molti altri linguaggi (compreso l'HTML e il LaTeX) per essere visualizzato e stampato facilmente. Uno dei vantaggi di questa cosa è che è più facile avere una bella versione cartacea, un'altro è che il documento ha i riferimenti interni e i link ipertestuali quando viene visualizzato sul web.
Questa revisione ha solo delle modifiche incrementali. Consiste principalmente di modifiche suggerite dai lettori, una delle quali è particolarmente importante.
La prima modifica è stata suggerita da Egil Kvaleberg
<
egil@kvaleberg.no>
,
che ha fatto notare il comando dump
in debugfs
. Grazie ancora, Egil.
La seconda è quella di menzionare l'uso di chattr
per evitare
di cancellare i file importanti. Grazie ad Herman Sujis
<
H.P.M.Suijs@kub.nl>
.
L'abstract è stato rivisto. Sono stati aggiunti degli URL per le organizzazioni ed il software. Sono state apportate altre modifiche minori (compresi alcuni errori di battitura e cose del genere).
L'ultima versione pubblica del documento dovrebbe essere sempre disponibile in formato testo nel sito del Linux Documentation Project (e nei suoi mirror).
L'ultima versione viene anche tenuta sul mio sito web in diversi formati:
È vitale ricordare che linux non è come l'MS-DOS quando si parla di recuperare file cancellati. Per l'MS-DOS (e la sua progenie bastarda Windows 95) generalmente recuperare un file è una cosa piuttosto semplice - il `sistema operativo' (uso il termine in un'accezione molto ampia) comprende addirittura anche un programma che automatizza la maggior parte del processo. Questo non è il caso di Linux.
Quindi, regola numero uno (il primo comandamento, se volete):
TENETE I BACKUP
in qualsiasi caso. Lo so, parla uno buono... dovrei piangere miseria (per essere uno studente bisogna avere qualche requisito) ed esortare tutti gli utenti benpensanti di Linux ad andare a comprare qualche utile dispositivo di backup, creare una tabella di backup decente e usarla. Per altre informazioni leggete il Frish (1995) (vedere la sezione Bibliografia e ringraziamenti).
In mancanza di backup, cosa fare? (o anche in presenza di backup: se avete dei dati importanti è, meglio andarci coi piedi di piombo).
Provate ad impostare i permessi dei file importanti a 440 (o meno):
negarvi il permesso di cancellare dei file implica una conferma
esplicita prima di cancellarli (io comunque trovo che, se sto cancellando
ricorsivamente una directory con rm -r
, interrompo il programma alla
prima o seconda richiesta di cancellazione e lo ridò come
rm -rf
).
Un buon trucco per i file selezionati è crearne un hard link in una directory nascosta.
Ho sentito una storia di un amministratore di sistema che ha cancellato ripetutamente
/etc/passwd
per errore (quindi praticamente distruggendo metà del sistema).
Una delle soluzioni sarebbe stata fare una cosa del genere (da root):
# mkdir /.backup
# ln /etc/passwd /.backup
Cancellare tutto il contenuto richiede un po' di sforzo: se dite
# rm /etc/passwd
fare
# ln /.backup/passwd /etc
la recupererà. Certo, non aiuta nel caso in cui abbiate sovrascritto il file, quindi tenete comunque dei backup.
Su un filesystem ext2 è possibile usare degli attributi ext2 per
proteggere i file. Questi attributi possono essere modificati con il
comando chattr
. Esiste un attributo `append-only' (sola
aggiunta): un file
con questo attributo non può essere cancellato, ma possono essere solo
aggiunti dei dati. Se una directory ha questo attributo, qualsiasi file
o directory in essa contenuti può essere modificato come il solito, ma non
possono essere cancellati dei file. L'attributo `append-only' si imposta con
il comando
$ chattr +a FILE...
C'è anche un attributo `immutable' (non modificabile), che si può impostare o togliere solo da root. Un file o una directory con questo attributo non può essere modificato, cancellato, rinominato e non ci si possono fare hard link. Si imposta così:
# chattr +i FILE...
L'ext2fs ha anche l'attributo `undeletable' (non cancellabile) (+u
in chattr
).
L'intenzione è che se un file con quell'attributo viene cancellato,
invece di essere veramente riutilizzato, viene soltanto spostato in un "posto sicuro"
per poter essere cancellato in un secondo tempo. Sfortunatamente questa caratteristica
non è stata ancora implementata nei principali kernel. Esistono comunque diverse
patch per i kernel che danno la possibilità di utilizzare questo tipo di cancellazione
reversibile: vedere
<
http://www.linuxhq.com/>
se vi interessa applicare le patch per questa caratteristica nel vostro kernel.
La patch più recente che conosco è quella di Rogier Wolff
<
R.E.Wolff@BitWizard.nl>
,
Darren J Moffat
<
darren@xarius.demon.co.uk>
e Kurt Huwig
<
kurt@huwig.de>
.
Vorrei evidenziare il fatto che anche se questa patch implementa la caratteristica di
cui ho parlato, non è per adesso una soluzione per il recupero di file. I file non
cancellabili vengono semplicemente spostati in un'altra directory, da cui un demone dovrebbe
eliminarli periodicamente.
Alcuni suggeriscono di rendere rm
un alias di shell o una funzione che stia per
rm -i
(che chiede conferma su qualsiasi file che cancellate). Addirittura le
versioni recenti della
distribuzione Red Hat
lo mettono per default a tutti gli utenti, compreso root. Personalmente, non riesco a
sopportare il software che non funziona da solo, quindi non faccio così.
C'è anche il problema che, prima o poi, userete la modalità a
utente singolo, o una shell diversa o addirittura una macchina diversa,
dove la funzione rm
che avete definito non esiste.
Se vi aspettate che vi venga chiesta conferma, è facile dimenticarsi dove vi
trovate e specificare troppi file al comando di cancellazione. Ugualmente, i vari script e
i programmi che sostituiscono rm
sono, IMHO, molto pericolosi.
Una soluzione leggermente migliore è cominciare ad usare un pacchetto che
gestisca la "cancellazione riciclabile" fornendo un comando che non si chiami rm
.
Per avere ulteriori dettagli su questo argomento, vedere Peek, et al (1993) (vedere la sezione
Bibliografia e ringraziamenti).
Dipende. Tra i problemi che insorgono nel recupero dei file su un sistema operativo di alta qualità, multitasking e multi-utente come Linux c'è quello che non si sa mai quando qualcuno vuole scrivere su disco. Quindi, quando al sistema operativo viene detto di cancellare un file, assume che i blocchi usati da quel file sono disponibili per allocare spazio per un altro file (è un esempio specifico di un principio generale di Linux: il kernel e gli strumenti relativi assumono che gli utenti non siano idioti). In generale, più viene usata la macchina, meno è probabile che riusciate a recuperare con successo i vostri file.
Inoltre, la frammentazione del disco può influire sulla facilità di recupero dei file. Se la partizione che contiene i file cancellati è molto frammentata, è poco probabile che riusciate a leggere un file intero.
Se la vostra macchina, come la mia, è effettivamente una workstation a utente singolo (la mia non ha ancora nemmeno una connessione di rete; forse l'anno prossimo), e non stavate facendo nessuna attività che scrivesse su disco al momento fatale della cancellazione dei file, potete aspettarvi una percentuale di recupero vicina a quella che ho indicato prima. Io ne ho recuperati all'incirca il 94% (ed erano file binari, notare). Penso che possiate essere contenti con voi stessi se ne riuscite a recuperare più dell'80%.
La procedura consiste principalmente nel trovare i dati a basso livello nella partizione, e nel renderli di nuovo visibili al sistema operativo. Ci sono principalmente due modi per farlo: uno è modificare il filesystem esistente in modo da rimuovere l'indicazione di "cancellato" dagli inode dei file in questione, e sperare che i dati ritornino magicamente a posto. L'altro metodo, che è più sicuro ma più lento, è capire dove i dati si trovano nella partizione e scriverli in un nuovo file.
Ci sono alcuni passi necessari da fare prima di iniziare a cercare di recuperare i dati: per altri dettagli vedere le sezioni Smontare il filesystem, Prepararsi alla modifica diretta degli inode e Prepararsi alla scrittura dei dati da qualche altra parte. Per sapere come fare in pratica a recuperare i file, vedere le sezioni Trovare gli inode cancellati, Ottenere i dettagli degli inode, Recuperare i blocchi di dati e Modificare gli inode direttamente.
Qualsiasi sia il metodo che avete scelto, il primo passo è smontare il filesystem che contiene i file cancellati. Vi sconsiglio fortemente di andare in qualsiasi modo a operare su un filesystem montato. Questo passo dovrebbe essere fatto al più presto possibile dopo che vi siete accorti della cancellazione dei file.
Il metodo più semplice è questo: assumendo che i file cancellati
siano nella partizione /usr
, fate
# umount /usr
Potete comunque voler mantenere disponibili alcune cose di /usr
, quindi
montatelo a sola lettura:
# mount -o ro,remount /usr
Se i file cancellati erano nella partizione di root, dovrete aggiungere l'opzione
-n
per evitare che mount cerchi di scrivere su /etc/mtab
:
# mount -n -o ro,remount /
A parte questo, è possibile che ci sia un altro processo che stia usando
il filesystem in questione (che farà fallire l'umount con un errore
di `Resource busy'). Esiste un programma che manda un segnale a qualsiasi processo
che sta usando un dato file o punto di mount: fuser
. Provatelo con la
partizione /usr
:
# fuser -v -m /usr
elencherà i processi coinvolti. Assumendo che nessuno di essi sia vitale, potete dare
# fuser -k -v -m /usr
per mandare ad ogni processo un SIGKILL
(che sicuramente lo ucciderà),
o ad esempio
# fuser -k -TERM -v -m /usr
per mandargli un SIGTERM
(che normalmente farà uscire il processo
in maniera pulita).
Il mio consiglio? Non fate così. Non credo che sia una cosa saggia giocare con un filesystem a livello abbastanza basso da fare funzionare questo metodo. Ci sono anche problemi nel senso che si possono recuperare in modo affidabile solo i primi 12 blocchi di ciascun file, quindi se avete dei file lunghi da recuperare dovrete usare l'altro metodo (leggete però la sezione Questo metodo diventerà più facile in futuro? per altre informazioni).
Se pensate di dover usare questo metodo, il mio consiglio è di copiare la partizione raw su una partizione diversa, e poi montarla usando il loopback:
# cp /dev/hda5 /root/working
# mount -t ext2 -o loop /root/working /mnt
Questo, comunque, richiede una versione di mount
recente (anche se
dovreste avere comunque la versione 2.6, dato che tutte le versioni
precedenti hanno un grande buco di sicurezza che permette l'accesso come root.
Le distribuzioni più diffuse, cioè la Debian, la RedHat e la
Slackware si sono aggiornate alla versione 2.6 di mount
).
Usare il loopback implica che quando distruggerete del tutto il filesystem (cosa che accadrà molto probabilmente), dato che tutto quello che dovrete fare è copiare di nuovo la partizione raw al suo posto e ricominciare.
Dovete assicurarvi di avere da qualche parte una partizione di recupero.
Magari, avete diverse partizioni sul vostro sistema: forse una di root, una
per /usr
, e una per /home
. Con tutte queste partizioni non
dovreste avere problema: create semplicemente una nuova directory in una
di esse.
Se avete solo una partizione di root, ed immagazzinate tutto su quella (come me, finché non mi metto sotto a ripartizionare), le cose sono leggermente più strane. Forse avete una partizione MS-DOS o Windows da usare? O avete il driver per il ramdisk nel kernel, forse come modulo? Per usare il ramdisk (assumendo che abbiate un kernel più recente dell'1.3.48), fate così:
# dd if=/dev/zero of=/dev/ram0 bs=1k count=2048
# mke2fs -v -m 0 /dev/ram0 2048
# mount -t ext2 /dev/ram0 /mnt
Questo crea un volume di ramdisk di 2MB, e lo monta su /mnt
.
Un breve avvertimento: se usate kerneld
per caricare e
scaricare automaticamente i moduli del kernel, allora non montate il
ramdisk finché non avete copiato tutti i file che vi si trovano
su un supporto non volatile. Una volta smontato, kerneld
assume che può smontare il modulo (dopo il normale periodo di
attesa), e una volta che ciò accade, la memoria viene riutilizzata
da altre parti del kernel, perdendo tutte le ore di fatica che avete fatto per
recuperare i vostri dati.
Se avete i nuovi dispositivi rimuovibili `superfloppy', probabilmente sono una buona scelta per metterci una partizione di recupero. Altrimenti, dovrete solo usare i floppy.
L'altra cosa di cui avrete bisogno è un programma che può leggere
i dati necessari dal mezzo del dispositivo della partizione. Per
iniziare, dd
adrà bene, ma per leggere diciamo, dal
600esimo MB in una partizione da 800 MB,
dd
insiste a leggere ma ad ignorare i primi 600 MB. Questo prende un
tempo piuttosto lungo. La mia soluzione per questo problema è stata
scrivere un programma che cercasse nel mezzo della partizione. Si chiama fsgrab
;
ne potete trovare il sorgente sul
mio sito web
e presto arriverà su
Sunsite
(e sui suoi mirror). Se volete usare questo metodo, il resto di questo mini-Howto
assume che abbiate fsgrab
.
Se nessuno dei file che state provando a recuperare è più lungo di
12 blocchi (dove un blocco di solito è un kilobyte), allora non avrete
bisogno di fsgrab
.
Se dovete usare fsgrab
ma non volete farlo, è piuttosto semplice
tradurre una linea di comando di fsgrab
in una di dd
. Se avete
fsgrab -c count -s skip device
allora il comando di dd
corrispondente è
dd bs=1k if=device count=count skip=skip
Vi devo avvisare che, anche se fsgrab
ha funzionato benissimo per me,
non posso prendermi alcuna responsabilità per il suo uso. È stata
una soluzione veramente veloce e improvvisata per fare funzionare le cose. Per altri
dettagli sulla mancanza di garanzia, vedere la sezione `Nessuna garanzia' nel file
COPYING
incluso con il programma (la GNU General Public License).
Il prossimo passo è chiedere al filesystem quali inode sono stati
liberati recentemente. È un compito che si può portare a termine con
debugfs
; avviatelo con il nome del dispositivo in cui è immagazzinato il
filesystem:
# debugfs /dev/hda5
Se volete modificare direttamente gli inode, aggiungete l'opzione -w
per
abilitare la scrittura sul filesystem:
# debugfs -w /dev/hda5
Il comando di debugfs
per trovare gli inode cancellati è lsdel
,
quindi, digitate il comando al prompt:
debugfs: lsdel
Dopo molti lamenti e stridore dei meccanismi del disco, un lungo elenco viene mandato
in pipe nel vostro pager preferito (il valore di $PAGER
). Ora vorrete
salvarne una copia da qualche altra parte. Se avete less
, potete digitare -o
seguito
dal nome di un file di output, altrimenti dovrete riuscire a mandare l'output da qualche
altra parte. Provate così:
debugfs: quit
# echo lsdel | debugfs /dev/hda5 > lsdel.out
Ora, basandovi solo sull'ora di cancellazione, la dimensione, il tipo e i permessi e l'owner espressi come numeri, dovrete riconoscere quali di questi inode cancellati sono quelli che vi servono. Con un po' di fortuna, potrete riconoscerli perché sono tutti quelli che avete cancellato circa cinque minuti fa. Altrimenti, cercate con attenzione su tutta la lista.
Suggerisco che, se possibile, stampiate la lista degli inode che volete recuperare. Vi renderà la vita molto più semplice.
debugfs
ha un comando stat
che stampa i dettagli su un inode. Date questo
comando per ciascun inode nella vostra lista. Ad esempio, se siete interessati all'inode
numero 148003, provate questo:
debugfs: stat <148003>
Inode: 148003 Type: regular Mode: 0644 Flags: 0x0 Version: 1
User: 503 Group: 100 Size: 6065
File ACL: 0 Directory ACL: 0
Links: 0 Blockcount: 12
Fragment: Address: 0 Number: 0 Size: 0
ctime: 0x31a9a574 -- Mon May 27 13:52:04 1996
atime: 0x31a21dd1 -- Tue May 21 20:47:29 1996
mtime: 0x313bf4d7 -- Tue Mar 5 08:01:27 1996
dtime: 0x31a9a574 -- Mon May 27 13:52:04 1996
BLOCKS:
594810 594811 594814 594815 594816 594817
TOTAL: 6
Se dovete recuperare moltissimi file, vorrete rendere questo passaggio automatico.
Assumendo che la lista degli inode da recuperare sia nel file lsdel.out
, provate
con questo:
# cut -c1-6 lsdel.out | grep "[0-9]" | tr -d " " > inode
Questo nuovo file, inode
, contiene il numero degli inode da recuperare, uno per
linea. Lo salviamo perché molto probabilmente tornerà comodo più
tardi. Date semplicemente:
# sed 's/^.*$/stat <\0>/' inode | debugfs /dev/hda5 > stats
e stats
conterrà l'output di tutti i comandi stat
.
Questa parte può essere molto semplice o molto poco, a seconda che il file che state cercando di recuperare sia più lungo di 12 blocchi.
Se il file non era più lungo di 12 blocchi, allora i numeri dei blocchi di
tutti i suoi dati sono immagazzinati nell'inode: li potete leggere direttamente
dall'output di stat
per l'inode. Inoltre, debugfs
ha un comando che fa
questo compito automaticamente. Per continuare con l'esempio di prima, ripetuto qui:
debugfs: stat <148003>
Inode: 148003 Type: regular Mode: 0644 Flags: 0x0 Version: 1
User: 503 Group: 100 Size: 6065
File ACL: 0 Directory ACL: 0
Links: 0 Blockcount: 12
Fragment: Address: 0 Number: 0 Size: 0
ctime: 0x31a9a574 -- Mon May 27 13:52:04 1996
atime: 0x31a21dd1 -- Tue May 21 20:47:29 1996
mtime: 0x313bf4d7 -- Tue Mar 5 08:01:27 1996
dtime: 0x31a9a574 -- Mon May 27 13:52:04 1996
BLOCKS:
594810 594811 594814 594815 594816 594817
TOTAL: 6
Questo file ha sei blocchi. Dato che questo corrisponde a meno del limite di 12,
usiamo debugfs
per scrivere il file in una nuova posizione, come
/mnt/recovered.000
:
debugfs: dump <148003> /mnt/recovered.000
Naturalmente, potete fare lo stesso con fsgrab
; qui sotto presento un esempio
del suo uso:
# fsgrab -c 2 -s 594810 /dev/hda5 > /mnt/recovered.000
# fsgrab -c 4 -s 594814 /dev/hda5 >> /mnt/recovered.000
Sia con debugfs
che con fsgrab
, ci saranno dei caratteri inutili alla fine
di /mnt/recovered.000
, ma non è molto importante. Se volete
sbarazzarvene, il metodo più semplice è prendere il campo Size
dall'inode, e metterlo nell'opzione bs
della linea di comando di dd
:
# dd count=1 if=/mnt/recovered.000 of=/mnt/resized.000 bs=6065
Naturalmente, è possibile che uno o più dei blocchi che compongono il vostro file siano stati sovrascritti. Se è così, siete sfortunati: quel blocco è perso per sempre (ma pensate se aveste smontato il filesystem prima!).
I problemi compaiono quando il file è più lungo di 12 blocchi di dati. Qui conviene sapere un po' come sono strutturati dei filesystem UNIX. I dati del file sono immagazzinati in unità chiamate `blocchi'. Questi blocchi possono essere numerati sequenzialmente. Un file ha anche un `inode', che è il posto in cui vengono immagazzinate informazioni come il proprietario, i permessi ed il tipo. Come i blocchi, gli inode sono numerati sequenzialmente, anche se con una numerazione separata. Una voce di una directory consiste nel nome del file e nel numero di un inode.
Ma con questo stato di cose è ancora impossibile per il kernel trovare i dati corrispondenti ad una voce di una directory, quindi nell'inode vengono anche registrati i numeri dei blocchi di dati del file, così:
Leggetelo ancora: lo so che è complesso, ma è anche importante.
Ora, l'implementazione corrente del kernel (di certo per tutte le versioni dalla 2.0.30 compresa) sfortunatamente azzera tutti i blocchi indiretti (e quelli doppiamente indiretti e così via) quando cancella un file; quindi se il file in questione era più lungo di 12 blocchi, non avete alcuna garanzia di riuscire a trovare nemmeno i numeri di tutti i blocchi componenti il file, pensate poi i loro contenuti.
L'unico metodo che sono riuscito a trovare finora è di assumere che il file non era frammentato: se lo era, siete nei guai. Assumendo che il file non fosse frammentato, ci sono diversi schemi per i blocchi dei dati, a seconda di quanti blocchi dati il file usava:
I numeri di blocco sono registrati nell'inode, come sopra descritto.
Dopo i blocchi diretti, contatene uno per il blocco indiretto, e poi ci sono 256 blocchi di dati.
Come prima, ci sono 12 blocchi diretti, uno indiretto (inutile), e 256 blocchi; questi sono seguiti da un blocco doppiamente indiretto (inutile), e 256 ripetizioni di un blocco indiretto (inutile) e 256 blocchi di dati.
Lo schema dei primi 65804 blocchi sono come nel precedente esempio. Poi segue un blocco triplamente indiretto (inutile) e 256 ripetizioni di una `sequenza doppiamente indiretta'. Ogni sequenza direttamente indiretta consiste di un blocco doppiamente indiretto (inutile), seguito da 256 ripetizioni di un blocco indiretto (inutile) e 256 blocchi di dati.
Naturalmente, anche se questi numeri di blocchi di dati assunti sono corretti, non c'è garanzia che i dati in essi contenuti siano intatti. Oltre a ciò, più lungo era il file, minore è la possibilità che sia stato scritto nel filesystem senza una frammentazione apprezzabile (eccetto in circostanze speciali).
Da notare che ho sempre assunto che la dimensione dei blocchi sia di 1024 byte, dato che è questo il valore standard. Se avete blocchi più grandi, alcune delle cifre riportate qui sopra sono errate. In particolare, dato che ciascun numero di blocco è lungo 4 byte, dimblocchi/4 è il numero di blocchi che può essere immagazzinato in ciascun blocco indiretto. Quindi, ogni volta che il numero 256 appare nella discussione qui sopra, sostituitelo con dimblocchi/4. Dovrete modificare anche i limiti sul `numero di blocchi richiesto'.
Esaminiamo un esempio di recupero di un file lungo.
debugfs: stat <1387>
Inode: 148004 Type: regular Mode: 0644 Flags: 0x0 Version: 1
User: 503 Group: 100 Size: 1851347
File ACL: 0 Directory ACL: 0
Links: 0 Blockcount: 3616
Fragment: Address: 0 Number: 0 Size: 0
ctime: 0x31a9a574 -- Mon May 27 13:52:04 1996
atime: 0x31a21dd1 -- Tue May 21 20:47:29 1996
mtime: 0x313bf4d7 -- Tue Mar 5 08:01:27 1996
dtime: 0x31a9a574 -- Mon May 27 13:52:04 1996
BLOCKS:
8314 8315 8316 8317 8318 8319 8320 8321 8322 8323 8324 8325 8326 8583
TOTAL: 14
Sembra esserci una possibilità ragionevole che questo file non sia frammentato: di sicuro, i primi 12 blocchi elencati nell'inode (che sono tutti blocchi di dati) sono contigui; quindi possiamo cominciare a recuperare quelli:
# fsgrab -c 12 -s 8314 /dev/hda5 > /mnt/recovered.001
L'ultimo blocco elencato nell'inode è 8583. Notate che stiamo ancora bene per quanto riguarda la contiguità del file: l'ultimo blocco di dati che abbiamo scritto era l'8582, che è 8327 + 255. Questo blocco 8583 è un blocco doppiamente indiretto, e quindi possiamo ignorarlo. È seguito da 256 ripetizioni di un blocco indiretto (che possiamo ignorare) seguito da 256 blocchi di dati; quindi, facendo un rapido conto, diamo i seguenti comandi. Notate che saltiamo il blocco indiretto 8583, e il blocco indiretto 8584 immediatamente (speriamo) successivo, e cominciamo a cercare i dati dal blocco 8585.
# fsgrab -c 256 -s 8585 /dev/hda5 >> /mnt/recovered.001
# fsgrab -c 256 -s 8842 /dev/hda5 >> /mnt/recovered.001
# fsgrab -c 256 -s 9099 /dev/hda5 >> /mnt/recovered.001
# fsgrab -c 256 -s 9356 /dev/hda5 >> /mnt/recovered.001
# fsgrab -c 256 -s 9613 /dev/hda5 >> /mnt/recovered.001
# fsgrab -c 256 -s 9870 /dev/hda5 >> /mnt/recovered.001
Facendo le somme, vediamo che finora abbiamo scritto 12 + (7 * 256) blocchi, che fa 1804. I risultati di `stat' per l'inode ci avevano dato un conteggio di 3616; sfortunatamente questi blocchi sono lunghi 512 byte (una conseguenza di UNIX), quindi in realtà ci servono 3616/2 = 1808 blocchi di 1024 byte. Ciò significa che ci servono ancora quattro blocchi. L'ultimo blocco scritto era il numero 10125. Come abbiamo fatto finora, saltiamo un blocco indiretto (il numero 10126), e poi possiamo scrivere quegli ultimi quattro blocchi.
# fsgrab -c 4 -s 10127 /dev/hda5 >> /mnt/recovered.001
Ora, con un po' di fortuna avremo recuperato l'intero file.
Questo metodo è, superficialmente, molto più semplice; comunque, come già detto, non può gestire file più lunghi di 12 blocchi.
Per ogni inode che volete recuperare, dovete impostare lo usage count a uno, e
il deletion time a zero: si fa con il comando mi
(modify inode) di debugfs
.
Un esempio di output, modificando l'inode 148003 di cui sopra:
debugfs: mi <148003>
Mode [0100644]
User ID [503]
Group ID [100]
Size [6065]
Creation time [833201524]
Modification time [832708049]
Access time [826012887]
Deletion time [833201524] 0
Link count [0] 1
Block count [12]
File flags [0x0]
Reserved1 [0]
File acl [0]
Directory acl [0]
Fragment address [0]
Fragment number [0]
Fragment size [0]
Direct Block #0 [594810]
Direct Block #1 [594811]
Direct Block #2 [594814]
Direct Block #3 [594815]
Direct Block #4 [594816]
Direct Block #5 [594817]
Direct Block #6 [0]
Direct Block #7 [0]
Direct Block #8 [0]
Direct Block #9 [0]
Direct Block #10 [0]
Direct Block #11 [0]
Indirect Block [0]
Double Indirect Block [0]
Triple Indirect Block [0]
Cioè imposto il deletion time a 0 e il link count a 1 e premete semplicemente invio per ciascuno degli altri campi. È garantito, è un po' noioso se avete molti file da recuperare, ma ci potete riuscire... altrimenti potete usare un `sistema operativo' grafico con un simpatico `Cestino'.
Tra l'altro: l'output di mi
si riferisce ad un campo `Creation time'
nell'inode. È una bugia! O comunque, trae in inganno. Il fatto è che
su un sistema UNIX non si può dire quando è stato creato un file.
Il membro st_ctime
di una struct stat
si riferisce al `tempo di modifica
dell'inode', cioè il momento in cui sia stato modificato un dettaglio dell'inode.
Qui finisce la lezione di oggi.
Notate che le versioni di debugfs
più recenti di quella che sto usando
probabilmente non includono alcuni dei campi che ho elencato sopra
(in particolare, Reserved1
e (alcuni) campi di fragment).
Una volta modificati gli inode, potete uscire da debugfs
e dire:
# e2fsck -f /dev/hda5
L'idea è che ciascuno dei file cancellati è stato recuperato,
ma nessuno di essi compare in un elenco di directory. Il programma e2fsck
può accorgersene, ed aggiungere una voce di directory per ciascun file
nella directory /lost+found
del filesystem (quindi se la partizione
è normalmente montata su /usr
, i file ora saranno in
/usr/lost+found
). Tutto quello che rimane da fare è scoprire il nome
di ciascun file dai suoi countenuti, e rimetterlo al suo posto corretto nell'albero
delle directory.
Quando usate e2fsck
avrete un output molto interessante, ed alcune
domande su quale danno riparare. Rispondete `sì' a tutto quello che si
riferisce alle `summary information' o agli inode che avete modificato.
Tutto il resto viene lasciato a voi, anche se di solito è una buona idea
rispondere affermativamente a tutte le domande. Quando e2fsck
ha finito potete
rimontare il filesystem.
In realtà c'è un'alternativa a fare lasciare i file in /lost+found
ad e2fsck
: potete usare debugfs
per creare un link all'inode nel filesystem.
Usate il comando link
di debugfs
dopo aver modificato l'inode:
debugfs: link <148003> pippo.txt
Questo crea un file pippo.txt
in quella che debugfs
crede sia la
directory corrente: pippo.txt
sarà il vostro file. Dovrete
ancora usare e2fsck
per aggiustare le informazioni di indice e i conteggi
dei blocchi e così via.
Sì. In effetti, credo che sia già così. I kernel
della serie di sviluppo 2.1.x non azzerano i blocchi indiretti da più di
sei mesi fa. All'inizio del dicembre 1996, c'è stata un po' di discussione
sulla mailing list linux-kernel
per produrre un altro kernel 2.0.x che
lasciasse anch'esso i blocchi indiretti intatti dopo l'eliminazione dei file.
Anche se fino alle versioni di anticipazione del kernel 2.0.31 questo ancora non
è successo, sospetto che sia fattibile. Una volta che Linus e gli altri
hacker del kernel superino questa limitazione nel kernel di produzione, molte delle
mie obiezioni alla tecnica della modifica manuale degli inode spariranno. Al limite
questo dovrebbe accadere al rilascio della serie 2.2.x, che (secondo le scale di tempi
dello sviluppo storico del kernel) dovrebbe accadere nel primo quarto del 1998.
Quando questo inconveniente verrà corretto, sarà anche possibile
usare il comando dump
nel debugfs
sui file lunghi.
In realtà esistono. Sfortunatamente credo che soffrano dello stesso problema della tecnica della modifica manuale degli inode: i blocchi indiretti non possono essere recuperati. Comunque, data la probabilità che questo non sarà a breve un problema, conviene dare un'occhiata a questi programmi già adesso.
Qualcuno in rete ha nominato lde
di Scott Heavner. Per essere onesti,
non lo raccomanderei come strumento per il recupero automatico dei file.
È più un debugfs
grafico che altro, anche se ha alcune caratteristiche
come la possibilità di cercare determinati tipi di file o determinati contenuti.
Funziona anche con i filesystem xia
(qualcuno lo usa ancora?) e minix
, cosa che
penso sia il motivo più forte per cui viene venduto in questi giorni.
La versione 2.3.4 è disponibile su
Sunsite
e sui suoi mirror (anche se è possibile che ce ne sia una versione più
recente; questa l'ho trovata su un archivio vecchio di 8 mesi su un CD-ROM). lde
ha della documentazione utile sui concetti base dei filesystem, come anche un
documento su come usarlo per recuperare i file cancellati. Anche se non l'ho usato,
sospetto che il mio metodo sia migliore.
Sembra che il programma che veramente funziona è il GNU Midnight Commander,
mc
. Si tratta di uno strumento di gestione di file full-screen, basato per quanto ne
so su un certo programma MS-DOS comunemente noto come `NC'. mc
supporta il mouse
per trucchi come fare cd
dentro un file tar. Tra i suoi filesystem virtuali ce n'è
uno per il recupero di file su ext2. Sembra molto comodo, anche se ammetto che non
l'ho mai usato personalmente -- preferisco i vecchi comandi di shell.
Apparentemente si deve configurare il programma con l'opzione --with-ext2undel
;
avrete anche bisogno delle librerie di sviluppo e dei file include
presenti nel
pacchetto e2fsprog
. Mi pare di capire che una volta compilato il programma, potete
dire di fare cd undel:
dev/hda5/, ed avere un `elenco di directory' dei file cancellati.
L'ultima versione non di sviluppo è probabilmente la 4.0; per quanto riguarda il kernel stesso, le versioni di sviluppo non sono raccomandate a chi non è un hacker. L'elenco di (oltre 70) siti di download è disponibile sul sito ufficiale di Midnight Commander 4, o provate il sito ftp ufficiali (che se la memoria non mi inganna è piuttosto lento).
Intendo produrre aggiornamenti regolari a questo documento finché avrò tempo per farlo e cose interessanti da dire. Ciò significa che sono avido di conoscere i commenti dei lettori. Posso essere più chiaro? Riuscite a pensare a qualcosa che possa rendere le cose più facili? Esiste qualche nuovo strumento che lo fa in automatico? Chi ha ucciso JFK?
Comunque, se avete qualcosa da dire, su questo documento o su qualsiasi altro
argomento, mandatemi due righe a
<aaronc@pobox.com>
.
`If I have seen farther than others, it is because I was standing on the shoulders of giants.' (Isaac Newton)
Molto di questo mini-Howto è derivato da un articolo su
comp.os.linux.misc
di Robin Glover
<
swrglovr@met.rdg.ac.uk>
.
Vorrei ringraziare Robin per avermi gentilmente permesso di rielaborare le sue idee in
questo mini-Howto.
Alcuni riferimenti bibliografici:
All trademarks are the property of their respective owners. Specifically:
This document is Copyright © 1997 Aaron Crane
<aaronc@pobox.com>
.
It may be freely redistributed in its entirety, including the whole of this
copyright notice, but may not be changed without permission from either the
author or the Linux Documentation Project Coordinator. Dispensation is granted
for copying small verbatim portions for the purposes of reviews or for quoting;
in these circumstances, sections may be reproduced in the presence of an
appropriate citation but without this copyright notice.
The author requests but does not require that parties intending to sell copies of this document, whether on computer-readable or human-readable media, inform either him or the Linux HOWTO Coordinator of their intentions.
L'unica licenza valida è quella originale in lingua inglese. Di seguito ne trovate una traduzione abbastanza fedele che però non ha alcun valore.
Tutti i marchi registrati sono proprietà dei rispettivi possessori. In particolare:
Questo documento è Copyright © 1997 Aaron Crane
<
aaronc@pobox.com>
.
Può essere liberamente distribuito nella sua interezza, inclusa tutta questa
nota di copyright, ma non può essere modificato senza permesso dell'autore o del
coordinatore del Linux Documentation Project. Viene data una dispensa per la copia di piccole
porzioni per recensioni o come citazione; in queste circostanze possono essere
riprodotte delle sezioni in presenza di una citazione appropriata, anche senza questa
nota di copyright.
L'autore si augura ma non richiede che chi intenda vendere copie di questo documento, sia su un mezzo leggibile su computer o da persone, informi lui o il coordinatore dei Linux HOWTO delle sue intenzioni.
Il coordinatore dei Linux HOWTO è Tim Bynum
<
linux-howto@sunsite.unc.edu>
.
Traduzione di Eugenia Franzoni, <eugenia@stud.unipg.it>
.