Verbinden Sie große überlappende Dateien

7

Ich versuche, eine (MySQL-) Datenbank von einer abgestürzten Festplatte wiederherzustellen. Es gibt eine Reihe von aktuellen Dumps, bei denen es sich um beschädigte bz2-Dateien handelt. Da sich die Datenbank nicht häufig ändert, sollten die Speicherauszüge nahezu identisch sein. bzip2recoverEtwa 70-80% der Chunks wurden aus den Dateien wiederhergestellt, sodass die meisten, wenn nicht alle Daten wiederhergestellt werden konnten, indem die Überlappungen in den Dateien gefunden und zusammengefügt wurden. Zum Beispiel:

dump1: |-----------------|xxxxxxxxxxxxxxxx|------------------|
dump2: |-------------|----------------|xxxxxxxxxxxxxxxxxxxxxx|
dump3: |xxxxxxxxxxxxxxxxxxxxxx|---------------|xxxxxxxxxxxxxx|

hier kann ich feststellen, dass der erste Block in dump1 durch den zweiten in dump2 fortgesetzt wird, der durch den zweiten in dump3 fortgesetzt wird, der durch den dritten in dump1 fortgesetzt wird. Durch das Zusammenfügen dieser vier Dateien habe ich die Daten wiederhergestellt.

Das Problem ist, dass es Tausende von Dateien gibt (ich habe zehn Speicherauszüge mit jeweils ~ 400 1M-Blöcken). Gibt es ein Tool, das diesen Prozess oder zumindest Teile davon automatisieren könnte (wie ein Linux-Befehl, der nach der längsten Überlappung zwischen dem Ende einer Datei und dem Anfang einer anderen sucht)?

Tgr
quelle
Die erste Frage muss lauten: Woher wissen Sie in einer bestimmten wiederhergestellten Datei, dass ein wiederhergestellter Block gültig ist? In Dump 3 oben zeigen Sie an, dass die Daten am Anfang des Dumps als gut bekannt sind, obwohl Sie keine andere wiederhergestellte Kopie haben, die diese Daten gemeinsam nutzt. Woher wissen Sie, dass dieser Datenbereich gültige Daten sind?
MadHatter
@MadHatter: Führt bzip2recovereine CRC32-Prüfung durch, bevor die Chunks extrahiert werden. Das Bild ist etwas irreführend: Ich kenne den Datenbereich bzip2nicht genau, teile die Datei vor der Komprimierung in ungefähr (aber nicht genau) 900 KB lange Blöcke auf, bzip2recoverextrahiere alle diese Blöcke und dekomprimiere die gültigen. Ich kenne also die gültigen Daten und ihre grobe Position, aber ich kenne nicht die genaue Länge der ungültigen Blöcke (sonst wäre dies viel einfacher).
Tgr

Antworten:

3

Ich brauchte genau das Gleiche. Ich habe mir diesen überraschend schnellen Python-Code ausgedacht (er hat zwei 2-GB-Dateien mit einer Überlappung von 800 MB in 30 Sekunden zusammengefügt.) Passen Sie die Überlappungsgröße nach Bedarf für Ihre Chunks an. Es sollte so lang wie möglich sein, aber kleiner als die tatsächliche Überlappungsgröße.

#!/usr/bin/env python

import sys

overlap_size = 100000000 # 100MB

a = file(sys.argv[1]).read()
b = file(sys.argv[2]).read()
end = a[-overlap_size:]
offset = b.find(end)

c = file(sys.argv[3], 'wb')
c.write(a[:-overlap_size])
c.write(b[offset:])
c.close()

Verwendungszweck:

./join.py chunkA chunkB outputAB
./join.py outputAB chunkC outputABC
./join.py outputABC chunkD outputABCD
...etc
ali1234
quelle
1

Ich habe kein Werkzeug für Sie, um die Arbeit vollständig zu erledigen, aber Sie können Werkzeuge verwenden wie:

cmp -l dump1 dump2

Dadurch erhalten Sie eine Liste der verschiedenen Bytes und ihrer Offsets. Bei der Überlappung wird kein Versatz von gedruckt cmp.

Sie können den ddBefehl auch verwenden, um einen Teil eines Speicherauszugs zu kopieren und an einen anderen Speicherauszug anzuhängen.

Sie können versuchen, ein eigenes Skript zu schreiben, das solche Tools verwendet, oder Sie können ein kleines C-Programm schreiben, das diese Dateien vergleicht und die erforderlichen Teile kopiert.

Ich hoffe, Sie finden diese Ideen hilfreich.

Khaled
quelle
1

Wie ein Linux-Befehl, der nach der längsten Überlappung zwischen dem Ende einer Datei und dem Anfang einer anderen sucht

Traditionell wäre dies diff. Es wird der "Unterschied" von zwei gegebenen Textdateien als Ausgabe zusammen mit einigen Steuerinformationen erzeugt (was hinzugefügt wurde, was entfernt wurde, welche Zeilen überprüft werden sollen). Der patchBefehl kann den Vorgang umkehren.

Theoretisch sollten Sie in der Lage sein, diffIhre verschiedenen Chunks zu verwenden, ein wenig an der Ausgabe zu arbeiten (z. B. die Befehle zum Löschen von Zeilen zu entfernen) und sie an patchfolgende Adresse weiterzuleiten :

# echo 'this
> is
> a' > file1
# echo 'a
> chunked' > file2
# echo 'chunked
> data
> file' > file3

# diff file2 file1 | egrep -v '^>' | patch -p0 -R file1 -o file12
patching file file1

# cat file12
this
is
a
chunked

# diff file3 file12 | egrep -v '^>' | patch -p0 -R file12 -o -
patching file file12
this
is
a
chunked
data
file
#

Beachten Sie, dass bei sehr großen Eingabedateien diffviel Speicher benötigt wird.

the-wabbit
quelle
Das Gedächtnis ist eines der Probleme; Das andere ist, dass diffes auf Linien basiert. MySQL-Dumps haben sehr lange Zeilen, und die Chunks werden bei Zeilenumbrüchen nicht aufgeteilt.
Tgr
@tgr Ob Sie lange Zeilen haben oder nicht, hängt im Wesentlichen von den mysqldump-Optionen ab, die beim Erstellen des Dumps verwendet werden. Aber wie Sie haben, wäre diff in der Tat nicht angemessen. Sie können sich das auch ansehen rdiff- es basiert auf rollierenden Prüfsummen anstelle von Zeilen, aber meiner Ansicht nach kann es nicht einfach mit Skripten versehen werden, sodass Sie wahrscheinlich in den Quellcode einsteigen müssen, damit es für Ihre Zwecke funktioniert .
The-Wabbit
1

Ich denke, Sie müssen ein solches Tool einfach selbst schreiben.

Beginnen Sie mit der größten Datei und kopieren Sie sie als Bild in den Speicher.

Führen Sie dann alle Dateien nacheinander durch und suchen Sie nach einer Überlappung mit dem ersten oder letzten Teil des aktuellen Speicherabbilds. Wenn Sie eine Überlappung finden, erweitern Sie das Speicherbild.

Wiederholen Sie diesen Vorgang, bis Sie alle Dateien durchlaufen haben, ohne Bytes hinzuzufügen. Schreiben Sie dann das Speicherbild in eine Datei.

David Schwartz
quelle