Випадково видалений файл у 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)
У виводі зверніть увагу на три ключові елементи:
- PID процесу (другий стовпець);
- файловий дескриптор (четвертий стовпець, наприклад 4w або 7w);
- позначку в кінці рядка, яка вказує, що файл видалено.
Якщо позначка 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 (для файлових систем ext4);
- testdisk і photorec (для ширшої підтримки різних файлових систем).
Ці утиліти працюють уже не з живими даними, а намагаються відновити їх із фрагментів на диску. Тому успіх не може бути гарантованим, особливо якщо після видалення активно записувалися нові дані.
Важливо: не варто запускати 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 значно комфортнішим.

