Wie kann ich zerstörte Dateien wiederherstellen auf reiserfs?

Im Folgenden geht es um die Wiederherstellung von verlorengegangenen Textdateien (z.B. txt, LyX, HTML) auf allen Dateisystemen, die Dateien im Klartext speichern (z.B. reiserfs, ext2).
Der Verlust kann sich auf versehentliches Löschen beziehen oder auch auf fehlende Syncs, d.h. nicht mehr geschriebene Dateistücke nach einem Stromausfall. In letzterem Fall wird man die Version wiederbekommen, die durch das letzte Speichern »überschrieben« wurde, oder eine der vorigen Versionen. Die Dateisysteme überschreiben die Dateien nämlich nicht wirklich, sondern sichern eine neue Version an anderm Ort und löschen die alte. Das Löschen geschieht, indem die entsprechende Inode als »deleted« vermerkt wird, ohne jedoch wirklich ihren Inhalt zu ändern. Also Verfahren:

  1. betroffenes Dateisystem unmounten, wenn nötig dann wieder read-only mounten:
    su
    Password:

    mit mount nachschauen, welche Partition betroffen ist. Dann:

     umount /home

    und read-only wieder mounten:

    mount -r -t reiserfs /dev/hda5 /home

    umount von /home ist als Benutzer root unmöglich, wenn das Homeverzeichnis von root selbst unter /home liegt. Das eigene Homeverzeichnis nämlich wird immer benutzt, selbst wenn man in keiner Shell in diesem Verzeichnis steht. Das liegt an geöffneten Dateien wie Konfigurationsdateien usw.

  2. Dateisystem in bearbeitbare Blöcke einteilen und an anderer Stelle speichern. Man benötigt also einigen Platz auf einer anderen Partition. Die Größe der Blöcke richtet sich nach dem verfügbaren RAM- und Swap-Speicher.
    Bei 192 MB RAM erwiesen sich Blöcke von je 100 MB als nicht zu viel.

    dd if=/dev/hda5 of=/hda5.block1.img bs=1M count=100
    dd if=/dev/hda5 of=/hda5.block2.img bs=1M count=100 skip=100

    und so weiter, bis alle mit du -h ermittelten Blöcke umkopiert wurden.

  3. Nun beginne man mit den letzten Blöcken (weil die neuesten überschriebenen Versionen der gesuchten Textdatei sich hinter älteren befinden) und arbeite sich weiter nach vorne. In jedem Block suche man eine für die gesuchte Textdatei in der neuesten Version charakteristische Zeichenkette, wähle eine angemessene Anzahl Zeilen Kontext (-) und speichere das Suchergebnis in einer Datei:
    grep -a -400 "Zeichen Kette" /hda5.part7.img > DateiGerettet.Versuch1.txt
  4. Man erhält in diesen Suchergebnissen eine Unmenge Variationen der gesuchten Datei, nämlich eine für jedes Mal, das man die Aktion »speichern« ausgewählt hat. Wieder beginne man mit den letzten Versionen, denn dies sind die neuesten. Hat man die beste Version gefunden, kann man sie abspeichern und hat seine verlorene Datei wieder. In vi:
    -g // geht zur letzten Zeile
    ?Zeichenkette // charakteristische Zeichenkette (als RegExp) vom Ende zum Anfang der Datei suchen
    n // nächste Suche, gleiche Richtung
    N // nächste Suche, entgegengesetzte Richtung
    :1204,1280w // Bereich in einer neuen Datei speichern
  5. Gegebenenfalls wurde die Datei fragmentiert gespeichert, d.h. die gefundenen Daten sind nur
    Bruchstücke der Datei. Dann muss man sich die Textdatei aus verschiedenen, einzeln zu suchenden
    Bruchstücken wieder zusammensetzen.
  6. Für weitere Informationen und bessere Verfahren vergleiche man das HowTo
    /usr/doc/packages/howto/en/mini/Ext2fs-Undeletion.gz
  7. Weitere hilfreiche Dinge:
    • ein grep direkt auf der betreffenden Partition mit ODER-Ausdrücken und dem Wissen, dass diese Ausdrücke am Beginn der gesuchten Texte vorkommen. Dabei wird in Unicode-Texten gesucht, die als UTF-8 gespeichert wurden:
      grep -E -a -B0 -A200 "1.Korinther 10|Matthäus 19|1.Korinther 9" /dev/hda4 > /opt/stZ.Komm.Versuch1.txt

      Das ermöglicht »undelete« mit im wesentlichem einem Befehl!
      Dabei kann es sein, dass eine Fehlermeldung wie »grep: /dev/hda4: Cannot allocate memory« auftritt. Vermutlich hält grep die über die Kontext-Optionen angegebenen Zeilen stets im Speicher, um bei Ergebnissen nicht schon gelesene Inhalte wieder lesen zu müssen. Wenn nun der Kontext mehr Speicher braucht als zur Verfügung steht entsteht die o.a. Fehlermeldung. Das ist möglich, weil Zeilen in Binärdateien ja eine zufällige, manchmal eben sehr große Länge haben. Wie man diesen Fehler umgehen kann:

      cat /dev/hda6 | strings | grep -B300 -A300 "Teilziele" > /tmp/rescued-snippets.txt

      Dieser Befehl benötigte etwa 2min/GB auf einem PIII mit 1,1GHz. Problematisch ist bei diesem Befehl jedoch, dass »strings« nur ASCII-Zeichen als Text betrachtet, also z.B. Umlaute und andere 8bit-Zeichen entfernt. Lösung: Mit Hilfe der Option »–radix=x« zu strings kann man wahrscheinlich die Position auf der Partition wieder ermitteln um mit dd (mit skip-Option) dann den gewünschten Inhalt inkl. gewünschtem (evtl. vergrößertem) Kontext direkt aus der Partition zu holen.

    • Erfahrungsgemäß besteht auch nach Wochen auf einem Einbenutzersystem noch eine reale Chance, eine verlorene Datei wiederzubekommen (zumindest wenn die Festplatte einige GB freien Platz hat).
      Es ist nicht notwendig, die Partition zu umounten, jedoch sollte man auf keinen Fall mehr eine Datei speichern. Mit guter Wahrscheinlichkeit zerstört man dadurch nämlich die gesuchte Datei, weil die neu gespeicherte Datei als Kopie in den (wahrscheinlich) wenigen noch freien Blöcken angelegt wird. In diesen Blöcken befindet sich aber auch die gesuchte, wiederherzustellende Datei!
      Gute Informationen zu Undelete unter ext2 (nicht aber unter ext3) gibt http://faq.jensbenecke.de/wiki/UnDelete .

Posted

in

,

by

Tags:

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.