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

UnixForum






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

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

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

Как восстановить удаленные файлы в файловой системе 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. Я не знаю, почему вывод команды говорит о том, что транзакция не была завершена (это выглядит очень маловероятным). Возможно, завершающий блок был перезаписан и эта старая транзакция журнала больше не завершится.