Site icon IT Education Center Blog – блог навчального центру DevOps – ITEDU by NETFORCE Group

Як відновити видалені файли в Linux

Випадково видалений файл у Linux не завжди означає, що ви безповоротно втратили свої дані.

Команда rm не стирає дані з диска миттєво — вона лише видаляє запис у файловій системі. Якщо ж якийсь процес усе ще використовує цей документ, ядро продовжує зберігати його дані, доки процес не закриє файл.

То як скористатися цим шансом і відновити видалений файл? Існує багато методів відновлення необроблених даних, але у цьому гайді ми покажемо найефективніші. 

Як знайти видалений файл у Linux

Для того, щоб відновити файл, нам спершу потрібно визначити його місцезнаходження. 

Тут знадобиться інструмент — Іsof. Це утиліта, що показує всі відкриті файли та процеси, які з ними працюють.

Якщо Isof немає у вашій системі, її можна легко встановити:

sudo apt install lsof [На Debian, Ubuntu та Mint ] 
sudo dnf install lsof [На RHEL/CentOS/Fedora та Rocky/AlmaLinux ]

Деякі команди в Linux потребують розширених прав доступу. Тому додайте sudo — він тимчасово надасть Isof права адміністратора системи (root). Це важливо, бо інакше ви не побачите файли, прив’язані до інших процесів: 

sudo lsof | grep deleted

Тепер ви можете знайти потрібний файл у списку — за назвою або тим самим рядком із виводу.

Приклад виводу:

nginx     1423  www-data   4w   REG  253,1  204800  131074 /var/log/nginx/access.log (deleted)
rsyslogd  1201      root   7w   REG  253,1  819200  131075 /var/log/syslog (deleted)

У виводі зверніть увагу на три ключові елементи: 

  1. PID процесу (другий стовпець);
  2. файловий дескриптор (четвертий стовпець, наприклад 4w або 7w);
  3. позначку в кінці рядка, яка вказує, що файл видалено.

Якщо позначка deleted відсутня, скористайтеся наступною командою:

sudo lsof +L1

Запуск lsof +L1 дозволяє побачити всі файли з кількістю посилань меншою за 1. 

Вивід: 

COMMAND   PID     USER   FD   TYPE DEVICE SIZE/OFF NLINKS     NODE NAME nginx    1423 www-data    4w   REG  253,1   204800      0   131074 /var/log/nginx/access.log (deleted)

Якщо в стовпці NLINKS = 0, це означає, що запис про файл у системі вже видалено, але його дані все ще залишаються в пам’яті. Це вказує на те, що котрийсь з процесів їх використовує.

Як відновити файл через /proc/fd

Після того як ви знайшли PID процесу та номер файлового дескриптора, можна перейти безпосередньо до відновлення.

Linux надає доступ до всіх відкритих файлів через каталог /proc. Для кожного процесу існує окрема директорія, а відкриті ним файли доступні за шляхом:

/proc/<PID>/fd/<FD>

Наприклад, із наведеного вище ми знаємо, що процес nginx має PID 1423, а потрібний файловий дескриптор — 4. Отже, шлях до файлу виглядатиме так:

/proc/1423/fd/4

Тепер потрібно скопіювати з допомогою команди сp в нове місце:

sudo cp /proc/1423/fd/4 /var/log/nginx/access.log.recovered

Якщо команда була виконана успішно, можна переходити до перевірки відновленого файлу. 

Не забудьте переконатися, що відновлений файл має вміст: 

ls -lh /var/log/nginx/access.log.recovered

Вивід:

-rw-r--r-- 1 root root 200K May  6 03:14 /var/log/nginx/access.log.recovered

Якщо розмір вибраного файлу збігається з розміром до його видалення, найімовірніше, відновлення пройшло успішно. Далі ви можете відновити файл у тому самому місці, де він зберігався раніше або почати працювати з його відновленою копією. 

Проте зверніть увагу, що команда cp копіює лише той стан файлу, який існував на момент виконання команди. Якщо процес і далі записує дані у видалений файловий дескриптор, нові записи не потраплять до відновленої копії — вона залишиться незмінною.

Файли журналів (log), які активно використовуються службами або застосунками, потребують окремої уваги. Після відновлення даних процес потрібно буде перезапустити, щоб він знову відкрив відповідний файл і продовжив запис у нього.

Що робити, якщо виникає помилка Permission denied

Найчастіше це означає, що команду запущено без відповідних прав доступу або ж сам процес уже завершився. 

Тому спочатку переконайтеся, що використовуєте sudo:

ps aux | grep 1423

Якщо помилка не зникла, перевірте, чи процес із потрібним PID ще працює. На жаль, якщо процес уже завершився, шлях /proc/<PID>/fd/<FD> зникає, і відновити файл цим способом не вийде.

Що робити, якщо процес завершився і закрив файл

Коли кожен процес, який тримав файл відкритим, закриває файловий дескриптор, ядро звільняє дискові блоки.

Після цього ви переходите в зону низькорівневого відновлення даних, тобто роботу з фізичними блоками диска. Тут використовуються інструменти:

Ці утиліти працюють уже не з живими даними, а намагаються відновити їх із фрагментів на диску. Тому успіх не може бути гарантованим, особливо якщо після видалення активно записувалися нові дані. 

Важливо: не варто запускати extundelete або будь-які інші інструменти відновлення на змонтованій файловій системі з доступом до запису. Спочатку розмонтуйте розділ або завантажтесь із Live USB. Інакше є ризик, що система перезапише ті самі блоки диска, які ви намагаєтесь відновити.

Як відновити видалені файли через Shell Script

Коли серед ночі падає продакшн, введення кількох команд підвищує ризик помилки. Shell Script автоматизує весь процес відновлення. Спочатку функція знаходить процес, який ще тримає видалений файл відкритим, а потім копіює його дані через /proc.

Тобто замість кількох команд вам достатньо просто передати їй назву файлу — далі вона зробить самостійно:

recover_deleted() {

 local filename="$1«

 local output="${2:-/tmp/recovered_file}"

 local result

 result=$(sudo lsof +L1 2>/dev/null | grep "$filename")

 if [[ -z "$result" ]]; then

   echo "No process holds $filename open. Data may already be gone."

   return 1

 fi

 local pid fd

 pid=$(echo "$result" | awk 'NR==1 {print $2}')

 fd=$(echo "$result" | awk 'NR==1 {print $4}' | tr -d 'rwu')

 echo "Found: PID=$pid FD=$fd"

 sudo cp "/proc/$pid/fd/$fd" "$output" && echo "Recovered to $output"

}

Щоб не вводити все вручну щоразу, збережіть цю функцію у своєму ~/.bashrc або у спільному файлі налаштувань для системних адміністраторів. Після цього команда буде повсякчас доступна в терміналі.

Далі введіть назву файлу та місце, де ви бажаєте його зберегти:

recover_deleted /var/log/nginx/access.log /var/log/nginx/access.log.recovered

Вивід:

Found: PID=1423 FD=4
Recovered to /var/log/nginx/access.log.recovered

Коли функція працює, вона може знайти кілька процесів, які все ще тримають один і той самий файл відкритим. У такому випадку застосовується awk NR==1, щоб взяти перший рядок результату. 

Далі з поля файлового дескриптора приберіть службові символи (r, w, u) через:

tr -d 'rwu'

Це потрібно для того, щоб залишити чистий номер дескриптора, який можна використати в шляху /proc.

Оскільки один і той самий файл може бути залучений одночасно в декілька процесів варто не поспішати, а перевірити який із них містить найбільш повні дані. Зазвичай це процес, який тримає у собі найбільший обсяг інформації.

Для перевірки можна подивитися розмір кожного варіанта вручну:

sudo ls -lh /proc/<PID>/fd/<FD>

Цей підхід допомагає обрати найбільш надійне джерело даних для відновлення. 

Як захистити файли від випадкового видалення: hard links і bind mounts

Якщо ви керуєте системою, де журнали пишуться в один файл, важливо подбати про їх безпеку навіть у разі випадкового видалення через rm.

Один із найпростіших способів зробити це — використати hard links. Вони створюють ще один запис у файловій системі, який вказує на той самий inode. У результаті файл має кілька шляхів доступу, а кількість посилань не падає до нуля, навіть якщо один із них буде видалено.

Наприклад:

ln /var/log/nginx/access.log /var/log/nginx/access.log.hardlink

Після цього треба перевірити чи обидва файли справді вказують на один і той самий inode:

ls -li /var/log/nginx/access.log /var/log/nginx/access.log.hardlink

Вивід:

131074 -rw-r--r-- 2 www-data www-data 204800 6 May 03:14 /var/log/nginx/access.log
131074 -rw-r--r-- 2 www-data www-data 204800 6 May 03:14 /var/log/nginx/access.log.hardlink

У цьому прикладі видно, що обидва записи мають однаковий inode 131074, а кількість посилань дорівнює 2. Це означає, що навіть якщо виконати rm /var/log/nginx/access.log, дані не зникнуть, вони залишаться доступними через hard link.

Ці посилання працюють лише в межах однієї файлової системи. Якщо потрібен механізм для прив’язки між різними файловими системами — використовуємо bind mount. Це процес, який дозволяє «прикріпити» наявний каталог до іншої точки в дереві файлової системи. 

Зробити це можна через команду:

mount --bind /var/log/nginx/access.log /var/log/nginx/access.log.backup

Підсумуємо

Ми впевнені, що вже після першого інциденту в продакшені ви будете дивуватися, як раніше працювали без цих прийомів. Зовсім скоро вони стануть звичною та зручною частиною вашої роботи з терміналом.

А знаєте, де ще можна отримати більше таких «чіт-кодів» для Linux? Звісно ж, на нашому курсі Linux для новачків. Там наші викладачі діляться не лише базовими знаннями та всім необхідним для впевненої роботи в системі, а й маленькими лайфхаками, які точно зроблять ваш досвід роботи з Linux значно комфортнішим.

Exit mobile version