Tags ?>
In der SuSE Supportdatenbank ist ein
Artikel
zu finden, der beschreibt wie man sich in so einem Fall weiterhelfen kann.
Zusammengefasst geht das so:
umount /dev/hdb5 debugfs /dev/hdb5
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:
debugfs: dump -p <48910> /root/restored/restored-file-1
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.
umount /dev/hdb5
mount /dev/hdb5 / -o ro,remount
defiant:~# debugfs -R lsdel /dev/hdb5 > deletedfiles.txt debugfs 1.22, 22-Jun-2001 for EXT2 FS 0.5b, 95/08/09
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 . . .
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 2001interessieren (in diesem Fall also die Jahreszahl) müssten wir alle Felder einzeln mit
read a b c d e f g h i j keinlesen.
do debugfs /dev/hdb5 -R "dump -p <$a> /root/restored/file$a" ; doneIm 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.
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; doneDamit werden alle, auch versteckte Dateien in einem Verzeichniss gemäss des Ausbaus von file2fext.pl (sieht Kommentare im Source) umbenannt "