 |
|
Gelöschte Dateien retten unter Linux
Wer hat nicht schon mindestens einmal schwungvoll ein rm abgesetzt und erst
nach dem Druck auf die Enter-Taste gemerkt, daß das doch nicht so beabsichtigt war?
In der SuSE Supportdatenbank ist ein
Artikel
zu finden, der beschreibt wie man sich in so einem Fall weiterhelfen kann.
Zusammengefasst geht das so:
- Das betroffene Dateisystem entmounten und debugfs aufrufen
umount /dev/hdb5
debugfs /dev/hdb5
- mit lsdel die gelöschten Files (bzw. deren Inodes) anzeigen lassen
defiant:~# debugfs /dev/hdb5
debugfs 1.22, 22-Jun-2001 for EXT2 FS 0.5b, 95/08/09
debugfs: lsdel
3 deleted inodes found.
Inode Owner Mode Size Blocks Time deleted
48910 0 100644 19988 5/ 5 Thu May 3 19:07:49 2001
48912 0 100644 19697 5/ 5 Thu May 3 19:07:49 2001
48914 0 100644 19694 5/ 5 Thu May 3 19:07:49 2001
debugfs:
- mit dump kann man nun die gelöschten Files auf eine andere
Partition zurückschreiben lassen. Die Verzeichnisstruktur in die
man schreibt muß natürlich schon existieren.
debugfs: dump -p <48910> /root/restored/restored-file-1
- Danach kann man sich dann freuen, daß man seine ach so wertvolle
Datei wieder zurückbekommen hat.
debugfs: quit
defiant:~# ls -l /root/restored/
insgesamt 20
-rw-r--r-- 1 root root 19988 19. Mär 22:13 restored-file-1
Soweit, so gut! Mit einer oder einigen wenigen Dateien geht das ja
noch. Wenn man aber so intelligent war, ein Verzeichnis mit richtig
vielen Dateien wegzubügeln (ich spreche da aus Erfahrung), ist es
natürlich äußerst unangenehm diesen Vorgang wer weiß wie oft zu
wiederholen.
Zum Glück ist debugfs aber sehr gut über die Kommandozeile zu
bedienen:
debugfs --help
debugfs 1.22, 22-Jun-2001 for EXT2 FS 0.5b, 95/08/09
debugfs: invalid option -- -
debugfs: Usage: debugfs [-b blocksize] [-s superblock] [-f cmd_file] [-R request] [-V] [[-w] [-c] device]
--help versteht es zwar nicht, sagt aber trotzdem welche Parameter und
Optionen es versteht. Ausführlichere Infos bekommt man natürlich über
die man-page.
Interessant sind hier die Parameter -f und -R. Mit -f kann man eine
Datei benennen, in der die debugfs-Kommandos stehen, während man mit
-R einen einzelnen Befehl an debugfs übergibt.
Zur Sache...
Für unser Beispiel gehen wir davon aus, ich hätte dummerweise einen
Haufen Dateien auf /dev/hdb5 gelöscht. Ziel ist es nun einigermaßen
bequem die wiederherzustellenden Files auszuwählen und diese dann
nicht alle einzeln eintippen zu müssen.
- Zunächst entmounten wir das betroffene Dateisystem:
umount /dev/hdb5
Falls das nun partout nicht möglich ist (z. B. weil es sich um das
root-Filesystem handelt) sollte man es wenigstens read-only mounten:
mount /dev/hdb5 / -o ro,remount
- Als nächstes wird eine Datei erzeugt, in der die Angaben über die
gelöschten Inodes stehen:
defiant:~# debugfs -R lsdel /dev/hdb5 > deletedfiles.txt
debugfs 1.22, 22-Jun-2001 for EXT2 FS 0.5b, 95/08/09
Dabei wird mit -R das schon bekannte lsdel übergeben und die Ausgabe
mit > statt auf den Bildschirm in eine Datei geschrieben.
- Mit unserem Lieblingseditor kann nun die eben erzeugte Datei
bearbeitet werden:
80 deleted inodes found.
Inode Owner Mode Size Blocks Time deleted
48910 0 100644 19988 5/ 5 Thu May 3 19:07:49 2001
48912 0 100644 19697 5/ 5 Thu May 3 19:07:49 2001
48914 0 100644 19694 5/ 5 Thu May 3 19:07:49 2001
585241 1000 100644 3915776 957/ 957 Mon Jul 16 23:11:17 2001
585242 1000 100664 3753819 918/ 918 Mon Jul 16 23:11:17 2001
585243 1000 100664 7203236 1762/1762 Mon Jul 16 23:11:17 2001
585244 1000 100664 2498472 611/ 611 Mon Jul 16 23:11:17 2001
585245 1000 100664 2492592 610/ 610 Mon Jul 16 23:11:17 2001
585246 1000 100664 9909104 2424/2424 Mon Jul 16 23:11:17 2001
585247 1000 100644 2893086 708/ 708 Mon Jul 16 23:11:17 2001
585248 1000 100644 3508372 858/ 858 Mon Jul 16 23:11:17 2001
585249 1000 100664 4312212 1056/1056 Mon Jul 16 23:11:17 2001
585250 1000 100664 4013104 981/ 981 Mon Jul 16 23:11:17 2001
.
.
.
Zunächst einmal müssen die beiden Zeilen am Anfang (die Auskunft über
die Anzahl der gefundenen Inodes und die Spaltenüberschrift) gelöscht
werden. übrig bleibt dann eine Liste aller auf der Partition
gelöschten Inodes. Nun muß man anhand der Angaben Owner (dahinter
versteckt sich die UID des Eigentümers) und Time deleted raten ob man
das jeweilige File zurück haben möchte. In der Regel dürfte wohl nach
"Massenlöschorgien" das Datum die hilfreichste Angabe sein.
Am Ende sollen in der Datei nur noch Zeilen mit den Angaben zu den
Inodes stehen, die wiederhergestellt werden sollen.
- Da wir jetzt eine mehr oder weniger lange Liste mit Inodes haben,
gilt es diese in geeigneter Weise debugfs zu
übergeben. Hierbei hilft uns die bash.
Wir pipen die Inode-Liste in eine Schleife, welche die Einzelteile
jeder Zeile in Variablen stellt und daraus den richtigen
debugfs-Aufruf macht:
cat deletedfiles.txt | while read a b; do
debugfs /dev/hdb5 -R "dump -p <$a> /root/restored/file$a" ;
done
Das sieht vielleicht auf den ersten Blick etwas kompliziert aus,
darum hier ein paar erläuternde Worte:
cat deletedfiles.txt |
gibt die Datei mit den Inodenummern statt auf den Bildschirm in eine
pipe.
Auf der anderen Seite der pipe wird unsere Datei dann Zeile für
Zeile von
while read a b;
gelesen. Dabei betrachtet read jede Zeile als eine Reihe von Feldern,
die durch Leerzeichen separiert sind. Jedes Feld wird einer der
genannten Variablen zugewiesen. Da uns nur der Wert des ersten Feldes
(die Inode-Nummer) interessiert, können wir den ganzen Rest der Zeile
einfach der Variablen b zuweisen. Angenommen uns würde auch noch der
letzte Wert der Zeile
585313 1000 100644 2082144 510/ 510 Mon Jul 16 23:11:18 2001
interessieren (in diesem Fall also die Jahreszahl) müssten wir alle
Felder einzeln mit
read a b c d e f g h i j k
einlesen.
do debugfs /dev/hdb5 -R "dump -p <$a> /root/restored/file$a" ; done
Im Schleifenkörper (der für jede Zeile aus deletedfiles.txt einmal
ausgeführt wird), steht der Aufruf von debugfs. Das auszuführende
Kommando wird mit -R übergeben, wobei $a durch die Inodenummer ersetzt
wird. Außerdem wird $a dazu benutzt eindeutige Namen für die
wiederhergestellte Datei zu erzeugen. Dabei sind die Anführungszeichen
wichtig um den Befehl, der per -R übergeben wird abzugrenzen.
Und so ganz nebenbei schützen sie die von debugfs geforderten spitzen
Klammern, die $a umschließen davor von der Shell als Umleitungszeichen
interpretiert zu werden.
-
Das war der einfache Teil!
Jetzt haben wir ein einen Haufen Dateien die file12234 usw. heissen,
aber keine Ahnug in welcher Datei sich der Brief an Tante Else oder
das Perl-Skript, das drei Nächte Arbeit gekostet hat befindet.
defiant:~/restored# ls
deletedfiles.txt file585306 file585309 file585312
file585304 file585307 file585310 file585313
file585305 file585308 file585311 restored-file-1
Eine einfach Möglichkeit um zumindest einen groben Überblick zu
bekommen ist, per file nachzusehen um was für Daten es sich bei jeder
Datei handelt. Da ich natürlich immer noch keine Lust habe, das für
jedes File einzeln einzutippen, liegt wieder die Verwendung
einer Schleife nahe:
defiant:~/restored# ls | while read a; do file $a; done
deletedfiles.txt: ASCII text
file585304: MPEG 1.0 layer 3 audio stream data, 128 kBit/s, 44.1 kHz, jstereo
file585305: MPEG 1.0 layer 3 audio stream data, 128 kBit/s, 44.1 kHz, jstereo
file585306: MPEG 1.0 layer 3 audio stream data, 128 kBit/s, 44.1 kHz, jstereo
file585307: MPEG 1.0 layer 3 audio stream data, 128 kBit/s, 44.1 kHz, jstereo
file585308: data
file585309: MPEG 1.0 layer 3 audio stream data, 112 kBit/s, 44.1 kHz, jstereo
file585310: MPEG 1.0 layer 3 audio stream data, 64 kBit/s, 32 kHz, jstereo
file585311: MPEG 1.0 layer 3 audio stream data, 64 kBit/s, 32 kHz, jstereo
file585312: MPEG 1.0 layer 3 audio stream data, 64 kBit/s, 32 kHz, jstereo
file585313: MPEG 1.0 layer 3 audio stream data, 128 kBit/s, 44.1 kHz, stereo
restored-file-1: ASCII text
Um genaues über den Inhalt der Files herauszubekommen muß man sie zwar
immer noch einzeln öffnen und ansehen, aber wer Lust hat, kann ja das
obige Kommando so modifizieren, daß Dateien deren Typ erkannt wird
gleich mit der korrekten Endung umbenannt werden.
"Und wenn sich jemand so einen Einzeiler ausgedacht hat,
möge er mir bitte eine Mail schicken, ich stelle das gerne hier
dazu." habe ich geschrieben, als ich diesen Text hier eingestellt
habe. Michael Schamber (5-d@gmx.net)
hat sich dazu folgende Lösung einfallen lassen:
"Der Einzeiler ist bei mir:
ls -A1 | while read FN; do EXT=`file $FN | file2ext.pl`; mv $FN $FN$EXT; done
Damit werden alle, auch versteckte Dateien in einem
Verzeichniss gemäss des Ausbaus von file2fext.pl
(sieht Kommentare im Source) umbenannt
"
Thomas de Klein
|
  |