Библиотека сайта rus-linux.net
Как восстановить удаленные файлы в файловой системе 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
, иначе вы не получите результата, поскольку не существует выходных файлов.