Können überschriebene Dateien wiederhergestellt werden?

42

Ich spreche nicht von der Wiederherstellung gelöschter Dateien , sondern von überschriebenen Dateien. Nämlich nach folgenden Methoden:

# move
mv new_file old_file

# copy
cp new_file old_file

# edit
vi existing_file
> D
> i new_content
> :x

Ist es möglich, etwas abzurufen, wenn eine der drei oben genannten Aktionen ausgeführt wird, vorausgesetzt, auf dem Linux-Computer sind keine speziellen Programme installiert?

Fragenüberlauf
quelle
4
Sie meinen, abgesehen von Ihren Backups?
Jasonwryan
@ Jasonwryan, ja, natürlich.
Fragenüberlauf
2
Ich möchte nur darauf hinweisen, dass Ihr erstes Beispiel ( mv) dem Löschen ähnelt old_file, nicht dem Überschreiben. In diesem Fall würden Methoden (falls vorhanden) zum Wiederherstellen gelöschter Dateien anstelle von überschriebenen Dateien angewendet. Ihre anderen beiden Beispiele überschreiben in der Tat eine bestehende old_fileund existing_filesind.
Celada
Alle drei von Ihnen bereitgestellten Beispiele werden implementiert, indem alle Datenblöcke der Originaldatei gelöscht und in neu zugewiesene Blöcke geschrieben werden. Das Verfahren zum Wiederherstellen dieser Daten entspricht dem Wiederherstellen einer gelöschten Datei. Eine Ausnahme kann sein, wenn die Originaldateien übermäßig kurz sind (kürzer als 60 Bytes bei ext4), wobei die letzten beiden Beispiele wahrscheinlich dazu führen, dass die vorherigen Daten nicht wiederhergestellt werden können.
Mark Plotnick
1
@ MarkPlotnick, so Celadas Kommentar, mvist anders.
Fragenüberlauf

Antworten:

60

Die Antwort lautet "Wahrscheinlich ja, aber es hängt vom Dateisystemtyp und dem Timing ab."

Keines dieser drei Beispiele überschreibt die physischen Datenblöcke von old_file oder existing_file, außer durch Zufall.

  • mv new_file old_file. Dadurch wird die Verknüpfung von old_file aufgehoben. Wenn es zusätzliche feste Links zu old_file gibt, bleiben die Blöcke in diesen verbleibenden Links unverändert. Andernfalls werden die Blöcke in der Regel (abhängig vom Dateisystemtyp) auf eine freie Liste gesetzt. Wenn dann das mvKopieren erforderlich ist (im Gegensatz zum Verschieben von Verzeichniseinträgen), werden neue Blöcke beim mvSchreiben zugewiesen .

    Diese neu zugewiesenen Blöcke können dieselben sein, die gerade freigegeben wurden, oder auch nicht . Bei Dateisystemen wie UFS werden Blöcke nach Möglichkeit aus derselben Zylindergruppe wie das Verzeichnis zugewiesen, in dem die Datei erstellt wurde. Daher besteht die Möglichkeit, dass das Aufheben der Verknüpfung einer Datei mit einem Verzeichnis und das Erstellen einer Datei in demselben Verzeichnis wiederverwendet werden ( und überschreiben) einige der Blöcke, die gerade freigegeben wurden. Aus diesem Grund wird Personen, die versehentlich eine Datei entfernen, standardmäßig empfohlen, keine neuen Daten in die Dateien in ihrem Verzeichnisbaum (und vorzugsweise nicht in das gesamte Dateisystem) zu schreiben, bis jemand versuchen kann, die Datei wiederherzustellen.

  • cp new_file old_filewird das Folgende tun (Sie können verwenden strace, um die Systemaufrufe zu sehen):

    open ("old_file", O_WRONLY | O_TRUNC) = 4

    Das O_TRUNC-Flag bewirkt, dass alle Datenblöcke freigegeben werden, genau wie mvoben. Und wie oben, werden sie im Allgemeinen zu einer freien Liste hinzugefügt und können durch die nachfolgenden Schreibvorgänge, die vom cpBefehl ausgeführt werden , wiederverwendet werden oder nicht .

  • vi existing_file. Wenn dies vitatsächlich vimder :xFall ist , führt der Befehl Folgendes aus:

    unlink ("existing_file ~") = -1 ENOENT (Keine solche Datei oder kein solches Verzeichnis)
    rename ("existing_file", "existing_file ~") = 0
    open ("existing_file", O_WRONLY | O_CREAT | O_TRUNC, 0664) = 3

    Es werden also nicht einmal die alten Daten entfernt. Die Daten werden in einer Sicherungsdatei gespeichert.

    Unter FreeBSD hat vidies open("existing_file",O_WRONLY|O_CREAT|O_TRUNC, 0664)die gleiche Semantik wie cpoben.


Sie können einige oder alle Daten ohne spezielle Programme wiederherstellen. Alles, was Sie brauchen, ist grepund ddund Zugriff auf das Raw-Gerät.

Für kleine Textdateien ist der einzige grepBefehl in der Antwort von @Steven D in der Frage, mit der Sie verknüpft sind, der einfachste Weg:

grep -i -a -B100 -A100 'text in the deleted file' /dev/sda1

Bei größeren Dateien, die sich möglicherweise in mehreren nicht zusammenhängenden Blöcken befinden, gehe ich folgendermaßen vor:

grep -a -b "text in the deleted file" /dev/sda1
13813610612:this is some text in the deleted file

Dies gibt Ihnen den Versatz in Bytes der übereinstimmenden Zeile. Folgen Sie dieser mit einer Reihe von ddBefehlen, beginnend mit

dd if=/dev/sda1 count=1 skip=$(expr 13813610612 / 512)

Sie möchten auch einige Blöcke vor und nach diesem Block lesen. Unter UFS sind Dateiblöcke normalerweise 8 KB groß und werden normalerweise ziemlich zusammenhängend zugewiesen, wobei die Blöcke einer einzelnen Datei abwechselnd mit 8 KB-Blöcken aus anderen Dateien oder freiem Speicherplatz verschachtelt werden. Das Ende einer Datei in UFS besteht aus bis zu 7 1-KB-Fragmenten, die möglicherweise zusammenhängend sind oder nicht.

Auf Dateisystemen, die Daten komprimieren oder verschlüsseln, ist die Wiederherstellung möglicherweise nicht so einfach.


Tatsächlich gibt es in Unix nur sehr wenige Dienstprogramme, die die Datenblöcke einer vorhandenen Datei überschreiben. Eine, die mir einfällt, ist dd conv=notrunc. Ein anderer ist shred.

Mark Plotnick
quelle
3
Vielen Dank für die Erklärung der inneren Mechanik der drei verschiedenen Vorgänge. Das ist wirklich nützlich!
Fragenüberlauf
btrfsist ziemlich widerstandsfähig gegenüber gelöschten Dateien. In der Regel werden Blöcke im Round-Robin-Modus verwendet. Wenn Sie also genügend Speicherplatz auf dem Gerät haben, wird die Datei für längere Zeit nicht überschrieben. Siehe hier
pqnet
Wie bekomme ich den vorhergehenden Textblock und was macht das Überspringen?
Unixit
@Islam Wenn Sie dd den skip=Parameter geben, wird diese Anzahl von Blöcken übersprungen , anstatt am Anfang der Eingabe zu lesen. Ein Block hat standardmäßig 512 Bytes, kann aber mit dem bs=Parameter geändert werden.
Mark Plotnick
1
@Islam Um den vorhergehenden Textblock zu erhalten, würde ich vorschlagen, einen skip=Wert anzugeben , der 1 Block (512 Byte) weniger ist. In meinem Beispiel $(expr 13813610612 / 512 - 1). Wenn dies nicht Ihren Wünschen entspricht, versuchen Sie es erneut, während Sie 16 oder 32 subtrahieren. Dadurch werden die Bereiche mit 8192 und 16384 Byte weniger berücksichtigt. Dateien werden häufig in 8192-Byte-Blöcken zugeordnet. Wenn Sie versuchen, eine größere Datei wiederherzustellen, versuchen Sie es mit einer höheren Anzahl, um Zeit zu sparen. Normalerweise benutze ich count=16und schaue mir das Ergebnis in einem Editor an, emacsder nichts dagegen hat, wenn einige der Daten kein Text sind.
Mark Plotnick
6

Ich werde nein sagen (mit einem riesigen Sternchen).

Überlegen Sie, wie Daten auf eine Festplatte gelegt werden. Sie haben Blöcke, die Daten enthalten und auf den nächsten Block verweisen (falls vorhanden).

Wenn Sie Daten überschreiben, ändern Sie den Blockinhalt (und wenn Sie die Datei erweitern, werden alle Endmarkierungen hinzugefügt). Also nichts sollte der Lage sein , zurückgewonnen werden (siehe unten).

Wenn Sie die Datei kürzen, verlieren Sie die alten Blöcke und sie werden bald recycelt. Wenn Sie ein Programmierer sind, denken Sie an eine verknüpfte Liste, bei der Sie die Hälfte Ihrer Liste "verlieren", ohne ein Befreien / Löschen durchzuführen. Diese Daten sind immer noch da, aber viel Glück beim Finden.

Es könnte interessant sein, über Fragmentierung nachzudenken.

Fragmentierung tritt auf, wenn Sie "Löcher" nicht zusammenhängender Daten auf Ihrer Festplatte haben. Dies kann dadurch verursacht werden, dass Sie Dateien so ändern, dass Sie sie erweitern oder kürzen und sie nicht mehr an ihrer ursprünglichen Stelle auf der Festplatte passen.

Wenn eine Datei über ihre ursprüngliche Größe hinauswächst (an dieser Stelle muss sie verschoben werden), können Sie je nach Dateisystem die gesamte Datei an einen neuen Speicherort kopieren, an dem sich die alten Daten noch befinden (aber als frei markiert sind). Oder Sie ändern einfach den alten Endzeiger und lassen ihn auf eine neue Position zeigen (dies führt zu einem Thrashing).

Kurz gesagt, Ihre Daten gehen wahrscheinlich verloren (ohne einen extremen forensischen Prozess zu durchlaufen, bei dem Sie sie unter dem Mikroskop betrachten). Es besteht jedoch die Möglichkeit, dass es immer noch da ist.

SailorCire
quelle
1
Ihre Antwort macht die Annahme , dass ein blockbasierten nicht-Copy-on-Write - Dateisystem wie ext4oder xfsin Gebrauch ist. Mit copy on write-Dateisystemen wie zfsund werden btrfsSie in der Tat nie "den Blockinhalt ändern"; Diese Dateisysteme verwenden immer brandneue Blöcke, um neue Daten aufzunehmen. Auch logbasierte Dateisysteme jffs2schreiben immer neue Daten an neue Speicherorte (keine "Blöcke", diese Dateisysteme sind nicht blockbasiert). Dies bedeutet jedoch nicht, dass es nicht einfach ist, den Speicherort der alten Daten zu ermitteln und zu ändern, bevor der Speicherplatz wiederverwendet wird. Ihre Antwort, die nein ist, ist also immer noch richtig
Celada
@ Celada Danke! Ich fand das sehr informativ. Ich hatte keine Zeit zu schauen, wie btrfs oder zfs funktionieren, aber ich wusste, dass es sie gibt.
SailorCire
2

Stellen Sie sicher, dass Sie genügend Speicherplatz in / var / tmp oder an einem großen Ort haben.

Versuchen

 grep -i -a -B100 -A100 'a string unique to your file' /dev/sda1 |
 strings > /var/tmp/my-recovered-file

wo / dev / sda1 wäre Ihre Festplatte in Ihrem System.

Dann durchsuchen Sie meine-wiederhergestellte-Datei nach Ihrer Zeichenfolge.

Es könnte meistens dort sein. Wenn Sie es finden, suchen Sie nach fehlenden Zeilenabständen, Klammern, Sysmbolen usw.

Verwenden Sie ein Suchwort aus Ihrer Datei, das ziemlich ungewöhnlich ist, oder eine Zeichenfolge, die die Datenmenge in der Datei verringert. Wenn Sie nach einem Wort wie "Echo" suchen, erhalten Sie viele Zeichenfolgen zurück, da das System viele Dateien mit dem Wort Echo enthält.

AndyM
quelle
0

Ich hatte eine Textdatei (VQ1.txt) mit Testdaten im Wert von 12 Stunden überschrieben Liste zeigte VQ1.txt ~ das hatte meine 'verlorenen' Daten!

$ cat VQ1.txt~  
Start time at: Thu Apr  2 18:07:23 PDT 2015
User, KW: 12hrFA_OEM_HelloVoiceQ
Test Case: 
Detection:  1, 1, 04-03 01:07:00.673 D/MultiKeywordBdctReceiver( 1743): vs status 258 : 2 : 1
Detection:  2, 1, 04-03 01:09:04.813 D/MultiKeywordBdctReceiver( 1743): vs status 258 : 2 : 1
Detection:  3, 1, 04-03 04:09:26.023 D/MultiKeywordBdctReceiver( 1743): vs status 258 : 2 : 1
Detection:  4, 1, 04-03 04:11:29.893 D/MultiKeywordBdctReceiver( 1743): vs status 258 : 2 : 1
Detection:  5, 1, 04-03 07:12:27.013 D/MultiKeywordBdctReceiver( 1743): vs status 258 : 2 : 1
Detection:  6, 1, 04-03 07:14:30.803 D/MultiKeywordBdctReceiver( 1743): vs status 258 : 2 : 1
Detection:  7, 1, 04-03 08:37:13.113 D/MultiKeywordBdctReceiver( 1743): vs status 258 : 2 : 1
Detection:  8, 1, 04-03 10:21:23.533 D/MultiKeywordBdctReceiver( 1743): vs status 258 : 2 : 1
Detection:  9, 1, 04-03 10:23:27.733 D/MultiKeywordBdctReceiver( 1743): vs status 258 : 2 : 1
Detection:  10, 1, 04-03 13:23:47.893 D/MultiKeywordBdctReceiver( 1743): vs status 258 : 2 : 1
Detection:  11, 1, 04-03 13:25:52.203 D/MultiKeywordBdctReceiver( 1743): vs status 258 : 2 : 1

12hrFA_OEM_HelloVoiceQ,  
KW detect count: 11
catsat
quelle
4
Ist das nicht eher eine Funktion bestimmter Texteditoren als von Unix im Allgemeinen? Mir ist kein Dateisystem bekannt, mit dem alte Versionen von Dateien auf diese Weise gespeichert werden.
Joey
0

TL; DR - Wenn die überschriebene Datei noch von einem laufenden Prozess geöffnet ist, kann dieser Blog-Beitrag Ihren Speck retten:

https://www.linux.com/news/bring-back-deleted-files-lsof/

Darin geht es um gelöschte Dateien, aber ich hatte viel Glück damit, auch mit einer Datei, die von rsync überschrieben wurde. Ich spreche von einer 60-GB-Datei, die von einer 4-MB-Datei überschrieben wurde, und konnte das Original wiederherstellen, da ich zum Glück den laufenden Prozess, der es offen hielt, nicht gestoppt hatte.

Fulv
quelle