Назад | Перейти на главную страницу

Объединяйте большие перекрывающиеся файлы

Я пытаюсь восстановить базу данных (MySQL) с разбитого диска. Есть несколько недавних дампов, которые представляют собой поврежденные файлы bz2. Поскольку база данных меняется нечасто, дампы должны быть почти идентичными. bzip2recover восстановил около 70-80% фрагментов из файлов, поэтому большую часть, если не все данные, можно было восстановить, обнаружив перекрытия в файлах и объединив их. Например:

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

здесь я могу обнаружить, что первый фрагмент в dump1 продолжается вторым в dump2, который продолжается вторым в dump3, который продолжается третьим в dump1. Объединив эти четыре файла, я восстановил данные.

Проблема в том, что файлов тысячи (у меня десять дампов по ~ 400 блоков по 1М каждый). Есть ли инструмент, который мог бы автоматизировать этот процесс или, по крайней мере, его часть (например, команда Linux, проверяющая максимальное перекрытие между концом одного файла и началом другого)?

Мне было нужно то же самое. Я придумал этот удивительно быстрый код Python (он объединил два файла размером 2 ГБ с перекрытием 800 МБ за 30 секунд). При необходимости измените размер overlap_size для ваших фрагментов. Это должно быть как можно дольше, но Меньше чем реальный размер перекрытия.

#!/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()

Использование:

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

У меня нет инструмента, чтобы вы могли полностью выполнить эту работу, но вы можете использовать такие инструменты, как:

cmp -l dump1 dump2

Это даст вам список разных байтов и их смещения. Перекрытие там, где нет офсетной печати cmp.

Также вы можете использовать dd команда для копирования части дампа и добавления ее к другому дампу.

Вы можете попробовать написать свой собственный скрипт, использующий такие инструменты, или вы можете написать небольшую программу на C, которая сравнивает эти файлы и копирует необходимые части.

Надеюсь, вы найдете эти идеи полезными.

как команда Linux, проверяющая максимальное перекрытие между концом одного файла и началом другого

Традиционно это было бы diff. На выходе он будет производить «разницу» двух заданных текстовых файлов вместе с некоторой управляющей информацией (что было добавлено, что было удалено, какие строки нужно проверить). В patch команда способна обратить процесс.

Теоретически вы должны уметь использовать diff на ваших разных кусках, немного поработайте над его выводом (например, удалив команды для удаления строки) и скармливайте его patch:

# 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
#

Обратите внимание: если у вас очень большие входные файлы, diff потребуется огромный объем памяти.

Думаю, вам просто придется самому написать такой инструмент.

Начните с самого большого файла и скопируйте его в память как свое изображение.

Затем просмотрите все файлы один за другим в поисках перекрытия с первым или последним фрагментом текущего образа памяти. Если вы обнаружите перекрытие, расширьте память образа.

Повторяйте, пока не пройдете через все файлы без добавления байтов. Затем запишите образ памяти в файл.