rm -rf не там: что реально можно спасти и как
Вы только что набрали rm -rf, нажали Enter — и через секунду поняли, что путь был не тот: опечатка, лишний пробел, скопированная не та строка из истории команд. Директория, которая была нужна, исчезла, а руки уже тянутся куда-то нажать ещё раз. Именно то, что вы сделаете в следующие 30 секунд, решает, останется у вас шанс на восстановление или нет. Ниже — конкретный порядок действий прямо сейчас, честная оценка шансов в зависимости от диска и файловой системы, и как выйти из этой ситуации так, чтобы она больше не повторилась.
Содержание
- Первое действие: не пишите больше ничего на этот диск
- Почему это работает: как на самом деле устроено удаление файлов
- Процесс всё ещё держит файл открытым — копируйте через /proc/PID/fd
- Восстановление на ext4 инструментами: extundelete, testdisk, photorec
- SSD и TRIM: почему шансы здесь намного ниже
- Снапшоты — если они есть, это ваш лучший шанс
- Как больше никогда не оказаться в этой ситуации
Первое действие: не пишите больше ничего на этот диск
Пока вы читаете эту статью, самое важное уже сформулировано в заголовке. Разверните это в конкретные шаги.
Ничего не выполняйте на разделе, где произошло удаление, даже ради «диагностики». Соблазн тут же создать файл с логом попытки восстановления, скачать утилиту в /root или написать заметку в текстовый файл — это то, что чаще всего убивает шанс на восстановление. Каждая новая запись на диск — это новые блоки данных, и файловая система с высокой вероятностью займёт под них именно те физические блоки, которые секунду назад пометила свободными после удаления ваших файлов.
Порядок действий:
- Если что-то ещё активно пишет на этот раздел (не сам
rm, а другой процесс — например, СУБД или логирование) — остановите его:systemctl stop <service>. - Если удалённые файлы были не на корневом разделе — размонтируйте раздел немедленно:
umount /mnt/data
- Если это корень или раздел нельзя размонтировать (на нём работает система) — переведите его хотя бы в режим только для чтения:
mount -o remount,ro /
- Если у вас есть второй диск или другой сервер — снимите посекторную копию раздела ДО каких-либо попыток восстановления и работайте дальше с копией, а не с оригиналом:
ddrescue -f -n /dev/sdb1 /mnt/backup-disk/image.img /mnt/backup-disk/image.log
Если ddrescue не установлен и ставить его негде без записи на нужный диск — используйте dd с другого носителя или через сеть (ssh на другую машину), но не пишите результат на тот же раздел: `` dd if=/dev/sdb1 bs=4M conv=noerror,sync | ssh user@other-host 'cat > /data/image.img' ``
- Не запускайте
fsckна разделе, где были удалённые файлы, «на всякий случай» —fsckсам активно пишет на диск и может перезаписать именно то, что вы пытаетесь спасти. - Не перезагружайте сервер в надежде, что «само починится». Перезагрузка — это дополнительные операции записи (логи, journal, systemd), которые тоже расходуют шанс.
На VPS без доступа к гипервизору принцип тот же: остановите всё лишнее внутри виртуалки и, если в панели хостинга есть rescue-режим, примонтируйте раздел через него в read-only.
Почему это работает: как на самом деле устроено удаление файлов
Чтобы не тратить время впустую, полезно понимать механику. В классических файловых системах вроде ext4 команда rm не стирает данные физически. Она:
- удаляет запись о файле из каталога (directory entry);
- помечает inode как свободный;
- помечает блоки данных, на которые указывал inode, как свободные в битовой карте (block bitmap).
Сами данные — те самые байты вашего файла — остаются на диске нетронутыми до тех пор, пока файловая система не решит выделить эти блоки под что-то новое. Это и есть окно возможностей: пока никто не записал новые данные в эти физические блоки, теоретически их можно прочитать напрямую, в обход обычной файловой структуры.
Проблема в том, что ext4 с журналированием часто обнуляет ссылки на блоки данных в inode ещё до их физического освобождения, что усложняет автоматическое восстановление метаданных — отсюда разница в инструментах: одни работают через журнал ФС (extundelete), другие ищут данные по сигнатурам содержимого, игнорируя файловую систему целиком (photorec, testdisk).
Отсюда же правило про секунды: на активно используемом сервере (логи, СУБД, кэши) новые блоки выделяются постоянно, и без остановки записи шанс тает с каждой секундой работы диска, а не с каждым часом.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверПроцесс всё ещё держит файл открытым — копируйте через /proc/PID/fd
Это самый надёжный сценарий восстановления из всех, и первое, что стоит проверить, если разговор идёт о конкретном файле (не о целой директории с конфигами, а, например, о логе или файле данных, который в момент удаления читал или писал какой-то процесс).
В Linux, пока хотя бы один процесс держит файл открытым, ядро не освобождает данные физически, даже если ссылка на файл в каталоге уже удалена — файл просто становится "невидимым" при обычном обращении по имени, но продолжает существовать как открытый файловый дескриптор.
Проверка, есть ли такие "осиротевшие" открытые файлы на разделе:
lsof +L1
Флаг +L1 показывает файлы со счётчиком ссылок (link count) меньше единицы — то есть удалённые, но всё ещё открытые. Пример вывода:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NLINK NODE NAME
postgres 4821 postgres 12u REG 253,1 8388608 0 5311234 /var/lib/postgresql/16/main/base/16401/16412 (deleted)
Здесь PID — 4821, дескриптор — 12. Данные всё ещё физически на диске, к ним можно обратиться через /proc:
ls -la /proc/4821/fd | grep deleted
cp --sparse=never /proc/4821/fd/12 /mnt/recovery/restored_file
Важные нюансы:
- Копируйте на другой раздел или диск, а не туда же, откуда восстанавливаете.
- Флаг
--sparse=neverвcpполезен для файлов баз данных — не даётcp"оптимизировать" нулевые блоки, что иногда портит структуру бинарных файлов СУБД. - Как только держащий файл процесс завершится — данные освобождаются и становятся уязвимы для перезаписи. Копируйте сразу, не откладывая на "после диагностики".
- Если это файл СУБД — не подсовывайте его тут же обратно живой базе; безопаснее поднять СУБД на копии данных отдельно и вытащить нужное через
pg_dump/mysqldump, либо восстановиться из штатного бэкапа — это надёжнее ручной реконструкции файлов данных.
Восстановление на ext4 инструментами: extundelete, testdisk, photorec
Если процесс уже не держит файл открытым или речь про целую директорию, переходите к инструментам восстановления. Они работают по-разному и это стоит понимать, чтобы не терять время.
extundelete — работает конкретно с ext3/ext4, читает журнал файловой системы, пытается восстановить структуру каталогов и имена файлов. Требует размонтированный раздел (в крайнем случае — read-only):
apt install extundelete
umount /dev/sdb1 # обязательно, иначе почти всегда ошибка "device busy" или порча данных
extundelete /dev/sdb1 --restore-directory var/www/html --restore-all
Результат складывается в ./RECOVERED_FILES/ в текущей директории (запускайте не на том же разделе). Сильная сторона — сохраняет оригинальные имена файлов и структуру каталогов, если журнал ещё содержит нужные записи. Слабая — журнал ext4 циклический и относительно небольшой, при активной работе раздела нужные записи в нём перезаписываются быстро, обычно счёт идёт на минуты активности диска, а не на часы.
testdisk — в первую очередь инструмент для восстановления таблиц разделов и загрузочных секторов, но умеет и восстанавливать удалённые файлы на ext-разделах через анализ структуры каталогов напрямую, без опоры на журнал:
apt install testdisk
testdisk /dev/sdb1
photorec (входит в тот же пакет) — принципиально другой подход: он вообще не смотрит на файловую систему, а сканирует раздел посекторно и ищет сигнатуры известных форматов файлов (заголовки JPEG, ZIP, PDF, SQL-дампов и т.д.):
photorec /dev/sdb1
Это делает photorec универсальным (работает даже при повреждённой файловой системе), но у него есть честное ограничение: он не восстанавливает оригинальные имена файлов и структуру директорий — вы получите папки recup_dir.1, recup_dir.2 с файлами вида f123456.jpg, и дальше придётся разбирать руками, что это и куда клалось.
Практический вывод: если нужны конкретные файлы с именами (конфиги, скрипты) — начинайте с extundelete, если он не сработал или файловая система уже не читается штатно — переходите к testdisk/photorec как к более медленному, но более живучему варианту.
SSD и TRIM: почему шансы здесь намного ниже
На вращающемся диске (HDD) блок данных физически остаётся тем, чем был, пока поверх него буквально не запишут новые биты — это то, на чём строится вся механика выше. С SSD честная картина другая, и важно сказать это прямо, а не создавать ложных надежд.
Современные SSD и файловые системы используют команду TRIM: когда файл удаляется, операционная система сообщает контроллеру SSD, какие страницы памяти освобождены. Контроллер использует эту информацию для wear leveling и сборки мусора (garbage collection) и часто проактивно стирает эти страницы на аппаратном уровне — не потому что кто-то что-то записал поверх, а потому что так устроена внутренняя оптимизация SSD. В результате данные могут физически исчезнуть за секунды-минуты после удаления, вне зависимости от того, писали вы что-то ещё на раздел или нет.
Проверить, активен ли TRIM на вашей системе:
cat /etc/fstab | grep discard
systemctl status fstrim.timer
Если в /etc/fstab у раздела стоит опция discard, TRIM отправляется сразу при удалении файла — это худший случай для восстановления. Если вместо этого используется периодический fstrim.timer (по умолчанию в современных дистрибутивах раз в неделю) — шанс есть, но зависит от того, когда в последний раз отработал таймер:
systemctl list-timers fstrim.timer
Честно: если TRIM активен и диск SSD/NVMe (а на VPS в 2026 году это подавляющее большинство конфигураций) — не тратьте часы на extundelete/photorec в надежде на чудо. Шанс объективно намного ниже, чем на HDD, и иногда равен нулю уже к моменту, когда вы дочитываете этот абзац. В такой ситуации переходите сразу к снапшотам — это единственный реально надёжный путь при SSD с TRIM. Подробнее о внутренней механике SSD — в статье про то, как SSD умирает медленно и при чём тут wear leveling.
Снапшоты — если они есть, это ваш лучший шанс
Прежде чем тратить время на инструменты из предыдущих разделов, проверьте — а не проще ли откатиться. Снапшот — это не вероятностное восстановление отдельных блоков, а точная копия диска на момент "до". Если он делался хотя бы за час до удаления — это надёжнее любого extundelete.
LVM. Если раздел находится на LVM-томе и снапшоты настроены заранее, проверьте их список:
lvs -a -o+lv_time
Если снапшот существует, смонтируйте его отдельно, не трогая рабочий том, и скопируйте нужное:
mkdir /mnt/snap
mount -o ro /dev/vgdata/data-snap /mnt/snap
cp -a /mnt/snap/path/to/needed/files /mnt/data/restored/
Если снапшотов не было — это урок на будущее, см. следующий раздел.
ZFS. Если раздел на ZFS, снапшоты там обычно автоматические (например, через zfs-auto-snapshot или sanoid):
zfs list -t snapshot -o name,creation -s creation | grep pool/dataset
ZFS удобен тем, что каждый снапшот автоматически доступен в скрытой директории без явного монтирования:
ls /pool/dataset/.zfs/snapshot/auto-daily/
cp -a /pool/dataset/.zfs/snapshot/auto-daily/path/to/file /pool/dataset/restored/
Полный откат датасета (zfs rollback pool/dataset@auto-daily) тоже возможен, но откатывает всё сразу, включая изменения, которые нужно сохранить — для точечного восстановления файлов лучше копировать из .zfs/snapshot/, а не делать rollback.
Облачные снапшоты диска. Если провайдер делал снапшот (по расписанию или ручной) — восстановите его в новый отдельный диск (не поверх текущего), подключите вторым диском к серверу и скопируйте нужное:
mount -o ro /dev/sdc1 /mnt/snapshot-restore
cp -a /mnt/snapshot-restore/path /mnt/data/
Проверка снапшотов должна идти до, а не после часа возни с photorec — если снапшот есть, это гарантированный результат вместо вероятностного.
Как больше никогда не оказаться в этой ситуации
Честный итог всей механики выше: результат восстановления никогда не гарантирован. Даже при идеальных условиях (HDD, файл только что удалён, диск не пишется) шанс высокий, но не стопроцентный. Поэтому основной вывод статьи — не "как восстанавливать", а "как не понадобится восстанавливать".
Двойная проверка перед rm -rf:
pwd && ls -la
Возьмите за привычку выполнять pwd прямо перед опасной командой, особенно если вы только что переключились между несколькими терминалами или SSH-сессиями на разные серверы — это самый частый источник ошибки "думал, что я на тестовом, а был на боевом".
Alias с подтверждением. Простой и рабочий вариант — включить интерактивное подтверждение для операций с несколькими файлами:
alias rm='rm -I'
Флаг -I (не -i) спрашивает подтверждение только при удалении более трёх файлов или при рекурсивном удалении директории — не превращается в утомительное "yes" на каждый файл, но страхует именно от rm -rf по ошибке.
Корзина вместо необратимого удаления. Для интерактивной работы (не для скриптов) можно подменить rm на инструмент с корзиной:
apt install trash-cli
alias rm='trash-put'
Удалённое лежит в ~/.local/share/Trash/ и его можно вернуть командой trash-restore, пока корзина не очищена вручную.
Защита скриптов от пустых переменных. Классический сценарий катастрофы — скрипт вида rm -rf "$TARGET_DIR"/*, где $TARGET_DIR оказался пустым, и команда фактически стала rm -rf /*. Добавляйте set -u в начало bash-скриптов, чтобы обращение к неопределённой переменной завершало скрипт ошибкой, а не подставляло пустую строку.
Регулярные бэкапы с проверкой восстановления. Снапшот спасает от "не туда", но не от порчи данных, которая реплицируется в бэкап. Настройте регулярное резервное копирование (restic, borgbackup) на отдельный диск или сервер и — это важно — периодически реально тестируйте восстановление из бэкапа, а не только факт его создания: бэкапы могут годами исправно запускаться и оказаться нерабочими в момент, когда понадобились, это отдельная и частая беда — она разобрана здесь. Если восстанавливаете конкретно базу данных из такого бэкапа — практические шаги описаны в статье про восстановление базы данных из бэкапа.
Снапшоты по расписанию для критичных серверов. Если сервер важен, настройте автоматические LVM- или ZFS-снапшоты по расписанию (раз в час/день) заранее, а не после инцидента — это дешёвая страховка именно от сценария "удалил не то, откатился за секунды". Если же диск уже пострадал по другой причине — физический сбой, а не человеческая ошибка — общий подход к восстановлению системы разобран в статье о восстановлении после сбоя диска.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Сколько у меня реально есть времени до того, как всё станет необратимо?
Однозначного числа нет — это зависит от активности записи на раздел и от того, HDD это или SSD с TRIM. На малоактивном HDD-разделе шансы остаются высокими часами, на активной СУБД на SSD с включённым discard счёт может идти на секунды. Действуйте так, будто времени мало, вне зависимости от типа диска.
Работает ли extundelete на других файловых системах, кроме ext3/ext4?
Нет, это узкоспециализированный инструмент именно под ext. Для XFS ситуация хуже: из-за особенностей дизайна файловой системы восстановление удалённых файлов штатными средствами почти не работает, там в первую очередь стоит рассчитывать на снапшоты или бэкапы. Для Btrfs и ZFS основной путь восстановления — это тоже снапшоты, а не carving-инструменты.
Стоит ли платить за коммерческое ПО или сервис восстановления данных?
Для логического удаления файлов (не физической поломки диска) бесплатных инструментов обычно достаточно. Платные сервисы восстановления данных больше оправданы при физическом повреждении носителя (битые сектора, отказ контроллера), а не при человеческой ошибке с rm -rf.
Что делать, если удалил файлы работающей базы данных (MySQL/PostgreSQL)?
Немедленно остановите СУБД (systemctl stop postgresql/systemctl stop mysql), чтобы она не продолжала писать WAL/binlog поверх освободившихся блоков. Дальше — либо восстановление через /proc/PID/fd, если процесс СУБД ещё держал файлы открытыми на момент удаления, либо восстановление из штатного бэкапа — это надёжнее ручной реконструкции повреждённых файлов данных.
Есть ли разница, если сервер арендованный (VPS), а не физический?
Команды выше выполняются так же внутри виртуальной машины. Разница — в возможностях провайдера: облачные снапшоты диска и rescue-режим с доступом к разделу в read-only — это стоит проверить в панели управления в первую очередь, ещё до extundelete и photorec.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →