Повернення з безодні, або відновлення файлів у UNIX, Журнал мережевих рішень
Ситуація, коли випадково видаляється якийсь важливий файл, несучи з собою у небуття всі свої біти та байти, — справжній жах для будь-якого системного адміністратора. У більшості випадків це швидше незручність, ніж трагедія, оскільки файли можна відновити за допомогою резервної копії, що регулярно оновлюється.
Однак якщо системний адміністратор або розробник з часу останнього резервного копіювання файлу встиг-таки внести до нього значні зміни, то неабияка кількість даних може виявитися втраченою. Неприємні ситуації цим не обмежуються: неправильно налаштовані сценарії резервного копіювання, збої в апаратному забезпеченні або, нарешті, просте невдачу. Ніщо не замінить правильну стратегію резервного копіювання. Не піддаючи цю тезу сумніву, у цій статті ми акцентуємо увагу на методах повного або часткового відновлення файлів у файловій системі UNIX.
ФАЙЛОВА СИСТЕМА UNIX
Файли в UNIX є логічні контейнери даних. З кожним файлом пов'язана так звана структура індексного дескриптора (inode, index-node structure), де містяться метадані (дискові блоки, на яких фізично розміщений файл), інформація про власника файлу, права доступу, розмір і т. д. При видаленні файлу індексні дескриптори фізично не стираються з диска, а відзначаються як вільні. Дані, що містяться в таких файлах, все ще зберігаються на диску і можуть бути відновлені, якщо на їх місце ще не встигли записати нову інформацію.
ПОВЕРНЕННЯ З БЕЗДНІ
Ця команда перетворила її файл із кодом Perl на файл розміром в нуль байт. Ситуація посилювалася ще й тим, що зміни, які відбуваються протягом тижня, не вносилисяспівробітницею в базу даних системи контролю версій (Concurrent Versions System, CVS), що означало втрату приблизно 600 рядків коду. Коли вона повідомила, що трапилося, її заспокоїли, пояснивши, що насправді великої біди немає, оскільки цей файл можна витягти з резервної копії, яка була зроблена минулої ночі, і їй доведеться відновити лише код, написаний сьогодні.
Я зателефонував нашому системному адміністратору і попросив його відновити цікавий для нас файл. Однак я не отримав відповіді, на яку розраховував, — системний адміністратор зізнався, що він жодного разу не чув про сервер розробки, і тому сервер не резервувався.
Співробітниця, упокорившись тим, що у файловій системі UNIX неможливо відновити видалений раніше файл, приготувалася витратити всі свої вихідні на повторне написання цього коду. Її запевнили, що відновлення файлу можливо, але для цього потрібно кілька годин. Зауважимо, що такі неприємні історії трапляються не лише з недосвідченими адміністраторами. Декілька років тому, працюючи в Linux, один з нас випадково надрукував crontab -d замість crontab -e. Чи багато читачів знайдеться користувачів, які роблять резервні копії /var/spool/cron/crontabs?
ВІДНОВЛЕННЯ ФАЙЛІВ UNIX
Як тільки якийсь файл був помилково видалений, необхідно відразу припинити на даному розділі жорсткого диска будь-які операції вводу/виводу. Розділ слід демонтувати або негайно після того, що сталося, перевести систему в режим одного користувача. Якщо це зробити неможливо (зокрема коренева файлова система не може бути демонтована), то всім працюючим у системі користувачам слід припинити свою роботу, а решті необхідно заборонити вхід до системи (наприклад, за допомогою файлу /etc/nologin). УУ деяких версіях UNIX існує можливість повторного монтування розділу лише для читання.
Головне - не допустити перезапис іншими процесами дискових блоків або індексних дескрипторів, раніше затребуваних віддаленим файлом. Це особливо актуально, якщо цей розділ майже заповнений, оскільки саме тоді можливість повторного використання віддалених індексних дескрипторів істотно зростає. Якщо рівень заповнення розділу невеликий, процедуру відновлення можна здійснити безпосередньо на змонтованому з можливістю читання/запису розділі диска, хоча, як було зазначено вище, шанси на відновлення при цьому неминуче зменшуються.
Далі описуються процедури відновлення файлів у системах UNIX. Перший розділ присвячений способу відновлення файлів з відомим вмістом, який можна застосувати практично для всіх різновидів файлових систем UNIX. Другий розглядає специфіку відновлення файлів у файловій системі Linux ext2.
ПРОЦЕС ВІДНОВЛЕННЯ ФАЙЛІВ З ВІДОМОГО ЗМІСТ
Після того, як система переведена в безпечний стан, необхідно за допомогою команди dd(1) зробити копію вихідних даних розділу, який містить віддалений файл. Припустимо, що помилково видалено файл /etc/passwd. Наступний приклад ілюструє процедуру створення копії кореневого розділу з наступним розміщенням її у файлі з розділу /export:
![]() |
Цільовий розділ повинен бути досить великим, щоб вмістити весь розділ-джерело (в даному випадку близько 128 Мбайт). Якщо в системі немає необхідного місця на диску, потрібно подумати про альтернативні дії, такі як монтування віддаленого розділу засобами NFS або виконання дій безпосередньо над файлом пристрою розділу.
Після тогояк копію файлової системи зроблено, систему можна повернути в розрахований на багато користувачів режим і продовжити роботу з нею в звичайному режимі. Якщо копію зробити не вдається, слід залишити систему в безпечному стані, а ім'я пристрою замінити на ім'я файлу (у прикладах, наведених нижче, /dev/dsk/c0t3d0s0 заміняються на /export/recover.dsk).
Описана процедура більше схожа на мистецтво, ніж на науку. Нехай видалено файл з ім'ям passwd. У лівій частині наведеної нижче інструкції команда cat(1) відображає всі рядки диска (опція -n передбачає виведення номерів рядків). Далі висновок перенаправляється утиліті fgrep(1), а та за вказаним їй регулярним виразом здійснює «швидкий» пошук запису root у файлі passwd:
У прикладі версії файлу /etc/passwd зберігалися на диску у трьох місцях. Версія GNU утиліти grep(1) надає опції -A та -B, що дозволяють виводити на друк кілька рядків, розташованих до і після знайденого за шаблоном рядка. Це полегшує видалення вмісту всього віддаленого файлу. Якщо grep(1) версії GNU не встановлена на вашому комп'ютері, ви можете скористатися програмою на Сu під назвою seekcat, наведеною в Лістингу 1. Вона виводить на друк весь файл, починаючи з певного зміщення в байтах або рядках. У програмі seekcat передбачено два незалежні параметри: перший вказується за допомогою прапора -b або -l, за ним слідує ціле число, що означає зміщення в байтах або рядках, з якого повинен починатися листинг. Другий параметр задається у вигляді прапора -f, а потім вказується ім'я файлу, що являє собою в даному випадку образ диска вихідних даних. Наприклад:
Такого ж результату можна досягти і шляхом вказівки утиліти seekcat початкового рядка. Цей номер береться зроздруківки, отриманої в результаті виконання команди cat -n, описаної раніше у поточному розділі. Програма seekcat виведе вміст файлу, починаючи з того місця, де було знайдено відповідний шаблон рядок. У наступному прикладі виводяться 10 рядків «образу диска», починаючи з першого знайденого рядка (рядок за номером 200 600). При необхідності можна повторити процес, задавши номер наступного знайденого рядка (у нашому прикладі номер 202 098):
ПРОЦЕС ВІДНОВЛЕННЯ ФАЙЛІВ В LINUX
Йтиметься про відновлення файлів у системі Linux у разі, якщо вони були видалені командою rm(1). Описана методика, як правило, гарантує відновлення файлів і не спирається на принцип проб і помилок. Додаткова її перевага полягає в тому, що вона дозволяє легко відновлювати двійкові файли та файли з невідомим вмістом.
Засіб, що використовується в процесі відновлення, відомий як відладник файлової системи debugfs(8), який зазвичай використовується для її перевірки та зміни стану. Хоча наведені нижче приклади написані для Linux, теоретично вони повинні бути справедливими для файлової системи будь-якого типу UNIX за умови, що в ній є засіб з функціональністю debugfs(8). Якщо такого засобу не буде, то доведеться користуватися методикою відновлення файлів з відомим вмістом.
Тут варто сказати, що debugfs - це потужний, але водночас надзвичайно небезпечний засіб. Воно надає безпосередній доступ до файлової системи, так що протягом сеансу роботи з ним необхідно бути обережними.
Утиліта debugfs(8) забезпечує інтерфейс на кшталт інтерфейсу командного процесора. Нас будуть цікавити три команди: lsdel, cat та dump. Запуститиdebugfs(8) у потрібному розділі можна так:
![]() |
За інформацією з висновку lsdel, можна з'ясувати, які з віддалених індексних дескрипторів представляють для нас інтерес. Найбільш важливі колонки з лістингу - Owner (Власник), Size (Розмір), Mode (Стан) та Time deleted (Час видалення). Якщо з моменту видалення файлу(ів) не було наступних операцій з диском, то дескриптори, які нас цікавлять, виявляться в кінці списку. У полі Owner (Власник) міститься ідентифікатор користувача — власник файлу, значення якого можна знайти в третьому полі файлу /etc/passwd. У нашому прикладі ім'я власника johnf (ідентифікатор 1000) та файл містить єдиний рядок important_data.
У наведеному вище лістингу дескриптор (inode) із номером 32605 знаходиться наприкінці списку і, отже, є першим кандидатом на перевірку. Вміст, що відповідає даному дескриптору, можна вивести так:
Отже, видалений файл знайдено. Команда dump «відновлює» файл, записуючи його на диск:
Ключ -p гарантує, що у файлу залишаться колишніми власник, група та права доступу.
Установка recover досить проста:
За промовчанням утиліта встановлюється в систему каталогів з коренем /usr. Будь ласка, прочитайте файл README з описом того, як встановити його в іншу систему каталогів. Під час сеансу роботи програма recover ставить кілька простих питань, наприклад:
- Хто є власником файлів?
- коли ці файли видалено?
- який приблизний розмір цих файлів?
Використовуючи отриману інформацію, recover запускає debugfs, відновлює відповідні даному критеріюіндексні дескриптори та поміщає їх у каталог, вказаний користувачем.
На жаль, на відміну від вмісту файлів, їх імена не можна відновити. Відновлені файли одержують імена, що складаються з префікса dump та номера наступного індексного дескриптора. При видаленні такого каталогу, як / etc, можуть бути втрачені сотні файлів. Для сортування відновлених файлів можна використовувати прості утиліти UNIX, серед яких найкорисніші strings(1) та file(1).
Програма strings(1) відображає послідовність символів ASCII, виймаючи її із зазначеного файлу. Ця утиліта зазвичай застосовується для «витягування» тексту з двійкових файлів, які не піддаються розшифровці іншими способами.
Утиліта file(1) допомагає з'ясувати тип файлу (наприклад, чи він є зображенням JPEG чи файлом PostScript) шляхом виконання низки тестів з допомогою деяких «магічних» чисел.
Такий результат роботи програми file(1) для каталогу з відновленими файлами:
![]() |
Класифікувати файли різних типів, додавши до імен файлів відповідні розширення можна за допомогою простого сценарію командного процесора. Наприклад:
У цьому випадку можна застосувати утиліту strings(1), вивівши на екран усі текстові рядки ASCII, що містяться у двійковому файлі. Наприклад:
![]() |
За цим текстом можна здогадатися, що файл є виконуваним файлом groff(1). Його запуск виконання з параметром --help підтверджує це. З бібліотеками дещо важче, бо їх не можна запустити. Тут нам на допомогу приходить команда objdump(1). Наприклад:
ВИСНОВОК
Жодні методи відновлення не замінять резервні копії даних,створювані регулярно та в повному обсязі на надійних носіях. Процедури, описані вище, - це допомога системним адміністраторам, які опинилися на краю прірви.
Поділіться матеріалом з колегами та друзями



