Неприятности случаются чаще, чем хотелось бы. Одной из них является удаление файла с важными данными. Причем в Unix, считается, что он отправляется в небытие. К сожалению, действительно, восстановление удаленных файлов в Unix не столь простая задача, как в Windows с ее привычной корзиной для удаленных файлов и многочисленными утилитами от сторонних поставщиков (к примеру, Norton Utilities). Это связано с особенностями архитектуры файловых систем Unix. ОС Linux более широко трактует понятие файла. Под файлом понимается любой объект, имеющий имя в файловой системе. Одним из таких объектов является каталог. В каталоге хранится как имя файла, так и дополнительная информация о файле - его размер, информация о владельце файла, местоположение на диске, дата создания, дата последней модификации, права доступа и много другое. Причем для эффективности, дополнительную информацию выносят в специальную структуру, а в каталоге оставляют только ссылку на эту структуру. При удалении файла эта дополнительная информация физически не удаляется с диска, а лишь отмечаются как свободные соответствующие блоки. Поэтому существует потенциальная возможность восстановления, удаленного файла, пока на место его расположения ничего не записывалось. Я попытаюсь предложить алгоритм действий при возникновении такой неприятности.
Прекращение дальнейшей работы.
Сразу после того, как вы осознали, что произошло нечто ужасное, прекратите дальнейшую работу на разделе диска с удаленным файлом. Естественно прекратить работу должны не только вы, но и все остальные пользователи, вошедшие в систему. Предпримите меры, чтоб больше никто не мог зайти в систему, пока вы будете заниматься восстановлением файла (например, с помощью /etc/nologin). Главное - не допустить перезапись ранее используемых удаленным файлом дисковых блоков другими процессами. Вероятность этого существенно возрастает, если раздел почти заполнен.
Сам себе некрофил.
Рассмотрим два варианта восстановления. Один
достаточно универсальный, применим, скорее всего, в
любой системе Unix. Второй - заточен под работу с
файловой системой Ext2 Linux.
Восстановление
файлов с известным содержимым
Будем считать, что удален файл из корневого раздела /etc/passwd и у вас нет проблем со свободным пространством на жестком диске.
* создаем копию корневого раздела и помещаем ее в файл из раздела /export. Этот раздел должен иметь достаточно свободного места, чтобы вместить в себя целиком раздел, на котором был удален файл
# df -k//export
File system Kbytes used avail
capacity Mounted on
/dev/dsk/c0t3d0s0 122070 19512
102558 16% /
/dev/dsk/c1t0d0s0 17592638 14425963
3166675 82% /export
# dd if=/dev/dsk/c0t3d0s0
of=/export/recover.dsk
263077+0 records
in
263077+0 records out
# ls -l
-rw-r-r-- 1
root other 134701056 Jul 1 16:54 recover.dsk
* запускаем команду cat с ключом -n (вывод номеров строк), вывод которой перенаправляем утилите fgrep, которая, осуществив поиск по заданному шаблону, отсечет все лишнее
# cat -n recover.dsk | fgrep "root:x:0:1"
200601
root:x:0:1:Super-User:/:/sbin/sh
202108
root:x:0:1:Super-User:/:/sbin/sh
строки могут быть и не найдены как в случае ошибки при задании шаблона, так и при потери содержимого удаленного файла, который мог быть переписан. В нашем случае, как видим, сохранилось две версии файла.
* выведем некоторое количество строк после
найденной
# fgrep -A10 "root:x:0:1" recover.dsk >
passwd
# cat
passwd
root:x:0:1:Super-User:/:/sbin/sh
daemon:x:1:1::/:
bin:x:2:2::/usr/bin:
...
ключи -A<число строк> и -B<число строк> утилиты fgrep позволяют выводить несколько строк, расположенных после (after) и до (before) найденной по шаблону строки. Если вы сможете получить весь свой файл за один шаг - то вам крупно повезло. Но, к сожалению, файлы обычно фрагментированы, и чем больше размер файла, тем выше вероятность фрагментации и больше самих фрагментов. Поэтому, скорее всего, придется повторять описанную процедуру, используя различные шаблоны и объединяя полученные части. Сложно бывает понять, какая из версий файла, сохранившихся на диске, последняя. Это определяется, только просмотром содержимого восстановленного файла. А значит, вам придется восстанавливать все версии файла. Довольно нудно, но эффективно.
Восстановление файлов в Linux Ext2
Этот метод применяется в случае удаления командой rm или функцией unlink и не требует при восстановлении знания содержимого удаленного файла. Для работы нам потребуется отладчик файловой системы debugfs довольно мощная утилита, применяемая обычно для проверки и изменения файловой системы и предоставляющая непосредственный доступ к файловой системе. Нам потребуются три ее команды:
Запускаем debugfs в требуемом разделе:
# debugfs /dev/hda8
debugfs 1.19,13-Jul-2000 for
EXT2FS 0.5b, 95/08/09
debugfs:
На приглашение
вводим команду lsdel(чашка кофе не помешает, поскольку
системе потребуется время на просмотр всего
раздела):
debugfs: lsdel
Inode Owner Mode Size Blocks Time
deleted
723300 1000 100664 27018 2/ 7 Mon May 20
19:08:17 2002
723301 1000 100444 1671 1/ 7 Tue May 20
19:08:17 2002
. . . . . . . . . . . . . . . . . . . .
. . . . . . . .
944887 1037 100600 597 1/ 1 Sun
Jan 26 20:05:00 2003
717281 1000 100400 1 1/ 1 Sun
Jan 26 20:05:13 2003
327101 1000 100644 15 1/ 1 Sun
Jan 26 20:07:06 2003
Лучше сразу перенаправить
вывод в файл, введя команду:
#echo lsdel |
debugfs /dev/hda6 > /tmp/lsdel-output
Если с
момента удаления не было операций с разделом, то
интересующие нас данные будут в конце списка. Посмотрим
содержимое, соответствующее последнему дескриптору,
набрав команду:
debugfs: cat
<327101>
my_very_important_data
Удаленный
файл найден, он содержал единственную строку. Команда
dump восстанавливает файл, записывая его на диск под
именем my_recovered_file:
debugfs: dump -p
<327101> /tmp/my_recovered_file
ключ -p
указывает на то, что у файла должны остаться прежними
владелец, группа и права доступа.
Восстановление группы файлов в Linux Ext2
Для восстановления группы файлов, целесообразно
воспользоваться утилитой Тома Пайка recover. Установка
стандартна:
# tar zxf recover-1.3.tar.gz
# cd
recover-1.3
# make
# make install
По
умолчанию утилита устанавливается в систему каталогов с
корнем /usr. Если надо установить в другое место -
читайте ReadMe. Во время работы recover задав несколько
простых вопросов, типа: кто является владельцем файлов,
когда эти файлы были удалены, каков приблизительный
размер этих файлов, запускает debugfs, и восстанавливает
соответствующие заданному критерию индексные
дескрипторы, помещая их в каталог, указанный
пользователем. К сожалению, имена файлов не подлежат
восстановлению. Восстановленные файлы получают имена,
состоящие из префикса dump и последующего номера
индексного дескриптора.
А что же мы восстановили?
Для идентификации восстановленных файлов используем две утилиты strings и file. Первая отображает последовательность символов ASCII, извлекая ее из указанного файла, вторая - выясняет тип файла (например, является ли он архивом или, скажем, файлом PostScript).
Запускаем утилиту file:
# file *
dump39788: directory
dump98008: PGP
armored text signed message
dump80154: gzip
compressed data, deflated, last modified: Sun Jan 28
03:31:21 2001, os: Unix
dump73290: ASCII
text
dump67095: ?diff? output
text
dump72945: JPEG file
dump9773: MPEG 1.0
layer 3 audio stream data, 128 kBit/s
dump8176: ASCII
C program text
dump58764: Bourne shell script
text executable
dump3223: troff or preprocessor input
text
Можно несколько автоматизировать
процесс, используя простейшие сценарии наподобие
следующего, добавляющего расширение к текстовым файлам
программ на языке С:
# for i in ?file * |
grep ? ASCII C program text? | \awk -F: ?{print
$1}??;
do mv $i $i.c; done
После определения
типа файлов попытаемся идентифицировать каждый файл. Для
тех, что содержат текст, код на С, звук или изображение
можно открыть соответствующими программами и попытаться
угадать первоначальное имя. Двоичные файлы, например
исполняемые файлы, библиотеки или файлы баз данных,
идентифицировать гораздо труднее. И если исполняемые
файлы или библиотеки проще не идентифицировать, а просто
переустановить недостающие, то с базами данных придется
повозиться. В этом случае придется применить утилиту
strings, выведя на экран все текстовые строки ASCII,
содержащиеся в файле.
# strings dump44768
По выводу можно догадаться, что данный файл является базой данных и открыть его соответствующей программой.
Заключение
Помните, ничто не заменяет регулярного резервирования. А применение методов, рассмотренных в статье, должно быть скорее исключением, чем правилом. Поверьте, ведь немного удовольствия от спуска в бездну небытия.