Библиотека сайта rus-linux.net
Как восстановить удаленные файлы в файловой системе ext3
Оригинал: HOWTO recover deleted files on an ext3 file systemАвтор: Карло Вуд (Carlo Wood)
Дата публикации: Март 2008
Перевод: Коваленко Алексей
Дата перевода: 03.09.2009 г.
Пример восстановления вручную
В следующем примере мы будем вручную восстанавливать маленький файл. В листинге приведена только часть вывода команды, для экономии места и для того, чтобы сделать пример более читаемым.
Используя ext3grep $IMAGE --ls --inode
мы находим имя файла, который хотим восстановить:
Очевидно, что инод 309631 стерт и мы не имеем номеров блоков для этого файла:
$ ext3grep $IMAGE --print --inode 309631 [...] Inode is Unallocated Group: 19 Generation Id: 2771183319 uid / gid: 1000 / 1000 mode: rrwxr-xr-x size: 0 num of links: 0 sectors: 0 (--> 0 indirect blocks). Inode Times: Accessed: 1202350961 = Thu Feb 7 03:22:41 2008 File Modified: 1202351093 = Thu Feb 7 03:24:53 2008 Inode Modified: 1202351093 = Thu Feb 7 03:24:53 2008 Deletion time: 1202351093 = Thu Feb 7 03:24:53 2008 Direct Blocks:
Поэтому мы будем искать его старую копию в журнале. Сначала мы найдем блок файловой системы, который содержит этот инод:
$ ext3grep $IMAGE --inode-to-block 309631 | grep resides Inode 309631 resides in block 622598 at offset 0xf00.
Затем мы найдем все дескрипторы журнала, ссылающиеся на блок 622598:
$ ext3grep $IMAGE --journal --block 622598 [...] Journal descriptors referencing block 622598: 4381294 26582 4381311 28693 4381313 28809 4381314 28814 4381321 29308 4381348 30676 4381349 30986 4381350 31299 4381374 32718 4381707 1465 4381709 2132 4381755 2945 4381961 4606 4382098 6073 4382137 6672 4382138 7536 4382139 7984 4382140 8931
Это означает, что транзакция с номером последовательности 4381294 имеет копию блока 622598 в блоке 26582 и так далее. Наибольший номер последовательности, находящийся внизу, должен быть последними данными записанными на диск и, таким образом, блок 8931 должен быть точно таким же, как текущий блок 622598. Для поиска последней, не удаленной копии, необходимо начинать снизу списка, и двигаться вверх.
Если вы попытаетесь вывести такой блок, ext3grep
распознает, что это блок из таблицы
инодов и будет выводить содержимое всех 32 инодов, находящихся в ней.
Однако мы хотим видеть информацию только об иноде 309631, поэтому используем grep
:
$ ext3grep $IMAGE --print --block 8931 | grep -A15 'Inode 309631' --------------Inode 309631----------------------- Generation Id: 2771183319 uid / gid: 1000 / 1000 mode: rrwxr-xr-x size: 0 num of links: 0 sectors: 0 (--> 0 indirect blocks). Inode Times: Accessed: 1202350961 = Thu Feb 7 03:22:41 2008 File Modified: 1202351093 = Thu Feb 7 03:24:53 2008 Inode Modified: 1202351093 = Thu Feb 7 03:24:53 2008 Deletion time: 1202351093 = Thu Feb 7 03:24:53 2008 Direct Blocks:
Это действительно то же самое, что мы видели в блоке 622598. Затем смотрим на меньшие порядковые номера, пока не находим инод с временем удаления (Deletion time), равным нулю. Первый, начиная с конца, который мы обнаруживаем, это блок 6073:
$ ext3grep $IMAGE --print --block 6073 | grep -A15 'Inode 309631' --------------Inode 309631----------------------- Generation Id: 2771183319 uid / gid: 1000 / 1000 mode: rrwxr-xr-x size: 40 num of links: 1 sectors: 8 (--> 0 indirect blocks). Inode Times: Accessed: 1202350961 = Thu Feb 7 03:22:41 2008 File Modified: 1189688692 = Thu Sep 13 15:04:52 2007 Inode Modified: 1189688692 = Thu Sep 13 15:04:52 2007 Deletion time: 0 Direct Blocks: 645627
Процессы, описанные выше, автоматизированы и могут быть выполнены гораздо быстрее при помощи
опции командной строки --show-journal-inodes
. Эта опция будет искать блок, к которому принадлежит инод, затем все копии блока в журнале, и последовательно выводить только запрошенные иноды из каждого из этих блоков (каждый из которых содержит 32 инода, как вы знаете), исключая дублирование:
Файл действительно мал, только один блок. Мы копируем этот блок командой dd
, как показано
ранее:
$ dd if=$IMAGE bs=4096 count=1 skip=645627 of=block.645627 1+0 records in 1+0 records out 4096 bytes (4.1 kB) copied, 0.0166104 seconds, 247 kB/s
и затем редактируем файл, удаляя добавленные нули, или копируем первые 40 байт (заданный размер файла).
$ dd if=block.645627 bs=1 count=40 of=start_azureus 40+0 records in 40+0 records out 40 bytes (40 B) copied, 0.000105397 seconds, 380 kB/s $ cat start_azureus cd /usr/src/azureus/azureus ./azureus
Файл восстановлен!
Обратите внимание, что можно просмотреть все дескрипторы заданной транзакции. Транзакция, которую мы использовали для восстановления этого файла, была 4382098. Полностью транзакцию можно увидеть, выполнив команду:
Здесь, как вы видите, например, TAG 6072=393218
означает, что блок 6072 содержит старую копию блока 393218. Я не знаю, почему вывод команды говорит о том, что транзакция не была завершена (это выглядит очень маловероятным). Возможно, завершающий блок был перезаписан и эта старая транзакция журнала больше не завершится.