Наши партнеры

UnixForum






Книги по Linux (с отзывами читателей)

Библиотека сайта rus-linux.net

На главную -> MyLDP -> Тематический каталог -> Файловые системы Linux

Как восстановить удаленные файлы в файловой системе ext3

Оригинал: HOWTO recover deleted files on an ext3 file system
Автор: Карло Вуд (Carlo Wood)
Дата публикации: Март 2008
Перевод: Коваленко Алексей
Дата перевода: 03.09.2009 г.

Восстановление файлов

Конечно, было бы весьма трудно восстанавливать этим путем большие файлы, состоящие из множества блоков, а представьте ручное восстановление тысяч файлов! Поэтому все, что представлено выше, может быть автоматизировано. Однако если Вы восстанавливаете 50 тысяч файлов, в сущности, невозможно впоследствии проверить, как прошло восстановление, особенно когда в результате получается файлов БОЛЬШЕ, чем вы в действительности хотели - слишком трудно найти все ненужные файлы. В действительности, вам необходимо бережно и аккуратно, насколько это возможно, подходить к восстановлению файлов.

Этого не требуется для восстановления единственного файла, вы можете просто передать путь к этому файлу ext3grep:

Обратите внимание, что в данном случае создается каталог RESTORED_FILES/carlo/bin в текущем каталоге, для того, чтобы иметь возможность восстановить этот файл. Также обратите внимание, что если RESTORED_FILES/carlo/bin/start_kvm уже существует в этом каталоге, то он не будет перезаписан!

Для выполнения работы по восстановлению, в первую очередь, вам необходимо пройти стадию 1 и стадию 2 анализа диска, которые так же выполняются программой ext3grep (смотрите ниже).

Имеется возможность выгрузить все имена файлов, которые ext3grep сможет найти, используя для этого опцию командной строки --dump-names:

Список файлов будет заканчиваться каталогом lost+found, это файлы, для которых не может быть найден каталог (однако, для них все еще есть копия инода в журнале). Наиболее вероятно, что эти файлы были удалены очень давно, и в любом случае могут быть исключены из рассмотрения.

После того, как вы получили удовлетворительный вывод --dump-names, вы можете заменить --dump-names опцией --restore-all, чье действие, по-сути, это вызов --restore-file для каждого имени файла, выведенного опцией --dump-names. Как упоминалось выше, очень рекомендуется использовать правильную опцию командной строки --after, для того, чтобы избежать попыток ext3grep восстановления очень старых файлов. Обратите внимание, что на данный момент вывод --dump-names не фильтруется, и только --restore-file (--restore-all) обеспечивается опцией командной строки --after.

Например,

где carlo/bin/startx только один файл, который был восстановлен. Этот файл был удален последним, и я установил значение --after на одну секунду раньше того, как это было сделано. Обратите внимание на логику того, почему этот файл был последним: поскольку я запускаю X этим скриптом, соответственно он использовался до того момента, пока я не перезагрузил систему.

Обращаю ваше внимание на тот факт, что проверка более чем 50000 файлов на разделе общим объемом 10 ГБ заняла 3,1 секунды, это очень быстро. Это вызвано несколькими факторами: 1) когда ext3grep запускается в первый раз, она выполняет полный анализ раздела и записывает результаты в файл кэша (за два шага; первый - стадия 1, и затем стадия 2). Эти стадии необходимы только один раз; 2) поскольку только один файл восстанавливался, доступ к диску больше не требовался (помимо того, я имею 4ГБ оперативной памяти в системе, - таким образом, все, что требовалось, уже было сохранено в кэше); 3) у моей системы очень быстрый процессор. Тем не менее, он использовался на 100% в эти 3,1 секунды. Время восстановления большого количества файлов, в основном, будет зависеть от скорости доступа к жесткому диску, однако и в этом случае работа программы остается относительно быстрой (вы можете просто сидеть и ждать результат).

Стадия 1

Стадия 1 создания кэш-файла - это запись в DEVICE.EXT3GREP.STAGE1, где DEVICE замещается именем устройства (т. е., если $IMAGE это /dev/hda2, то DEVICE это hda2). Мало что может быть сделано неправильно на стадии 1, - это просто сканирование целого диска и поиск всех блоков, которые выглядят как содержащие каталоги.

Формат кэш файла на стадии 1 выглядит следующим образом:

В первой части первая колонка - это иноды, после которых идет пробел, затем двоеточие и еще один пробел, разделяющие список номеров блоков, которые используют этот инод для записи каталога с именем ".". Очевидно, что может быть только один каталог, который использует этот инод, таким образом ext3grep определяет, который, из этих номеров блоков, является последним реальным номером. Вторая часть списка - это все номера блоков, которые содержат расширенные блоки каталогов, т. е. блоки каталогов, которые не являются первым блоком и не содержат записи каталога с именем ".". Какому каталогу они принадлежат неизвестно до тех пор, пока неизвестен номер оригинального инода. На стадии 2 ext3grep будет пытаться найти, какому каталогу принадлежат эти блоки.

Стадия 2

Эта стадия выполняется через функцию init_directories(), содержащую, в большинстве своем, эвристический код. Во-первых, она определяет, какой блок является реальным стартовым блоком каталога, и затем назначает каждый расширенный блок каталога одному из этих каталогов (смотрите также раздел "Что еще сделать?" ниже). Как результат, появляется возможность назначить имя пути к каждому (каталогу) иноду и назначить им список блоков каталога. Наконец, этот результат записывается в файл кэша (DEVICE.EXT3GREP.STAGE2). В случае, если здесь что-либо пойдет неправильно, вы имеете возможность внести исправления, отредактировав этот файл, удалив некорректные или добавив корректные номера блоков. Однако, не удаляйте и не добавляйте комментарии, - ext3grep будет работать некорректно, если вы слишком сильно измените файл.

База данных locate

Каюсь, для того, чтобы восстановить файлы, я воспользовался ещё кое-чем, кроме данных в моем разделе: у меня все еще был раздел /var, и поэтому все еще была база данных locate (в /var/cache/locate/locatedb). Я использовал ее для составления списка имен всех файлов, которые были удалены, и записал их в файл locate_output в следующем формате:

carlo
carlo/.Trash
carlo/.Xauthority
[...]

Другими словами, в том же формате, что и вывод --dump-names. Этот файл открывался и использовался через функцию load_locate_date, в исходном файле locate.cc, которая заполняет карту filename_to_locatepath_map. Эта карта впоследствии используется функцией parent_directory для того, чтобы строить предположения о том, какому родительскому каталогу отнести заданное имя файла.

Даже тогда, поскольку моя база данных locate не была полной, мне потребовалось вручную вносить поправки. В частности, можно добавить в файл locate.cc жестко запрограммированный список регулярных выражений, которые будут вызывать возврат в определенный родительский каталог. Дополнительно я так же жестко закодировал перевод трех номеров блоков (каталогов) в "lost+found". Возможно вам придется настроить/исправить эту часть кода, если вы хотите достичь успеха в правильном восстановлении ваших данных в корректный каталог.

Если вы видите сообщения типа указанного ниже:

Could not find an inode for extended directory at BLOCKNR, disregarding it's contents. 
(Невозможно найти инод для расширенного каталога в BLOCKNR, игнорирую его содержание.)

Тогда, пожалуйста, прочитайте эту заметку полностью для получения дополнительной информации.

Излишние жесткие ссылки

Поскольку иноды используются повторно, зачастую случается, что старая запись каталога (для удаленного файла или в удаленном каталоге, или в старом блоке каталога), не используемая нигде больше, ссылается на инод, который в настоящий момент используются чем-то еще. Если это что-то того же самого типа, что и старая запись (например, два обычных файла) то не существует пути чтобы отличить их от жестких ссылок: двух файлов использующих один и тот же инод. Как результат, после восстановления появляется множество НЕПРАВИЛЬНЫХ жестких ссылок.

Для того чтобы упростить очистку от этих ссылок в ext3grep существует опция командной строки --show-hardlinks.

Здесь жесткие ссылки для инода 309562 - корректные. Жесткая ссылка для инода 702474 неправильная, и один из этих файлов должен быть удален. После того как будет выполнено ручное определение, какой из этих файлов неправильный, и его удаление, он не будет отображаться в выводе команды при ее повторном запуске. Будет показан отчет только о тех жестких ссылках, которые все еще существуют в выходном каталоге. Вы можете использовать --show-hardlinks только после выполнения программы с опцией --restore-all, иначе вы не получите результата, поскольку не существует выходных файлов.