Диск забит наследством: что можно удалить, а что держит систему
Вам достался сервер, который настраивал кто-то другой, и первое, что бросается в глаза — df -h показывает 96%, а то и 100%. На таком диске страшно трогать что угодно: непонятно, какие файлы держат работающие сервисы, а какие можно снести без последствий. Старый администратор недоступен, документации нет, а гуглить «что за файл /var/lib/something/data-old» бесполезно — это специфика конкретной системы. Ниже — методичный порядок: как найти, куда делось место, разложить находки по корзинам «точно можно удалить», «похоже на мусор, но нет» и «сначала проверьте», и не устроить на унаследованной машине аварию в первый же день работы с ней.
Содержание
Сначала — не удаляйте ничего, снимите картину диска
Первое правило разборки чужого забитого диска: ни одна команда в первый час не должна ничего удалять. Задача первого прохода — построить карту, где именно лежит место, а не тушить пожар вслепую. Начните с общей картины:
df -h
df -i # инозулы кончаются отдельно от места — стоит проверить сразу
Если df -i показывает Use% под 100% при свободном месте на диске — это отдельная проблема (обычно миллионы мелких файлов, часто в кэшах или сессиях), и решается она не тем же способом, что нехватка байтов.
Дальше — спуск по дереву каталогов. du без параметров на всём / будет считать вечность и упрётся в псевдофайловые системы (/proc, /sys), поэтому сразу ограничивайте охват и глубину:
du -x -h --max-depth=1 / 2>/dev/null | sort -rh
Флаг -x критичен: он запрещает du пересекать границы файловых систем. Без него, если на сервере есть примонтированные тома (/mnt/backup, сетевой диск, второй раздел под /data), вы посчитаете чужое место как часть корня. Дальше спускайтесь в найденный «тяжёлый» каталог тем же способом:
du -x -h --max-depth=1 /var 2>/dev/null | sort -rh
du -x -h --max-depth=1 /var/lib 2>/dev/null | sort -rh
Если на сервере можно поставить пакет, ncdu экономит массу времени: он строит то же дерево, но интерактивно, с навигацией стрелками и сортировкой на лету.
apt install ncdu # Debian/Ubuntu
dnf install ncdu # AlmaLinux/RHEL
ncdu -x /
Отдельно проверьте топ самых старых и самых больших файлов — это часто быстрее находит виновника, чем обход по каталогам:
find / -xdev -type f -size +500M -exec ls -lh {} \; 2>/dev/null | sort -k5 -rh
find / -xdev -type f -mtime +365 -size +100M 2>/dev/null
Второй запрос ловит крупные файлы, которые никто не трогал год — хороший маркер забытого, а не рабочего файла. Но сам по себе возраст ничего не доказывает: файл конфигурации базы, который просто не обновлялся, тоже будет старым и нужным. Зафиксируйте вывод в файл на этом этапе — вы ещё вернётесь к нему, когда будете сверять «стало ли легче» после каждого удаления.
Что почти всегда безопасно удалить
После обзора обычно проступает несколько типовых категорий мусора, которые встречаются на унаследованных серверах чаще всего.
Ротированные и старые логи. Логротейт по умолчанию хранит несколько недель сжатых архивов — если конфиг logrotate был настроен небрежно (или не настроен вообще), архивы копятся годами.
find /var/log -name "*.gz" -mtime +90 -exec ls -lh {} \;
find /var/log -name "*.log.[0-9]*" -mtime +90
Перед удалением убедитесь, что архивы не нужны юридически — если у бизнеса есть требования хранить логи доступа N месяцев, сначала выгрузите их в холодное хранилище, а потом уже чистите локально.
Кэши пакетных менеджеров. Это почти всегда чистый выигрыш без риска — кэш восстанавливается сам при следующей установке пакета.
apt-get clean # Debian/Ubuntu, чистит /var/cache/apt/archives
dnf clean all # AlmaLinux/RHEL
npm cache clean --force # если Node ставился глобально, а не только в контейнерах
pip cache purge
На серверах, где годами накатывали обновления без apt-get clean в cron, /var/cache/apt/archives может занимать несколько гигабайт.
Journald без лимита. Systemd-журнал может расти неограниченно, если размер не зафиксирован в конфиге.
journalctl --disk-usage
journalctl --vacuum-size=500M
Это безопасная операция, если только на сервере специально не настроен долгий аудит-лог для комплаенса — в этом случае размер стоит выяснить заранее.
Старые ядра и orphaned-пакеты. На Ubuntu/Debian после серии обновлений без чистки в /boot и /lib/modules могут висеть образы старых ядер, каждый по 100-300 МБ.
dpkg -l | grep linux-image
apt autoremove --purge
Оставьте хотя бы одно предыдущее ядро на случай, если новое не грузится — не удаляйте всё, кроме текущего, за один проход.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверDocker: где прячутся гигабайты
На унаследованных серверах с Docker диск чаще всего забивают не логи и не бэкапы, а сам движок контейнеров — образы, слои сборки и логи контейнеров, о которых никто не думает как о диске.
docker system df -v
Эта команда сразу показывает разбивку: сколько занимают образы, контейнеры, тома и build cache, причём отдельно — сколько из этого «reclaimable». На заброшенных серверах build cache часто оказывается неожиданно огромным — годы CI-сборок без docker builder prune в расписании.
Логи контейнеров — отдельная частая причина: драйвер json-file по умолчанию не ограничен по размеру, и болтливое приложение с debug-логированием может нагенерировать десятки гигабайт в одном файле.
du -h $(docker inspect --format='{{.LogPath}}' $(docker ps -aq)) 2>/dev/null | sort -rh
Если находите такие файлы — не удаляйте их через rm напрямую, пока контейнер жив (подробнее почему — в следующем разделе); правильный путь — обрезать через truncate -s 0 или настроить ротацию логов на будущее:
truncate -s 0 /var/lib/docker/containers/<id>/<id>-json.log
И добавить лимит в daemon.json, чтобы проблема не вернулась:
{
"log-driver": "json-file",
"log-opts": { "max-size": "20m", "max-file": "3" }
}
Дальше — сами образы и тома, зона повышенной осторожности: docker image prune -a удалит все образы, не привязанные ни к одному контейнеру, а docker volume prune снесёт все тома без подключённого контейнера прямо сейчас. На унаследованной системе легко попасть в ловушку: контейнер, который запускается раз в месяц по cron, в момент чистки не запущен, и его образ или том попадёт под нож.
docker image ls -a # сначала посмотрите список глазами
docker image prune -a --filter "until=720h" # безопаснее: только старше 30 дней
docker volume ls # и здесь тоже — руками, не автоматом
Более подробный разбор про подчистку самого движка контейнеров есть в статье про регулярную чистку docker-образов, томов и сетей, а если конкретно логи контейнеров съели весь диск — отдельный разбор в статье «Docker съел весь диск логами».
Забытые бэкапы и дублирующиеся дампы БД
Третий частый виновник — ручные дампы баз данных и архивы, которые кто-то когда-то сделал «на всякий случай» и забыл удалить.
find / -xdev \( -name "*.sql" -o -name "*.sql.gz" -o -name "*.dump" -o -name "*.tar.gz" \) -size +100M 2>/dev/null -exec ls -lh {} \;
Здесь важна не команда, а дисциплина проверки перед удалением. Найденный дамп может быть:
- рабочей копией текущего продакшена, которая дублирует автоматический бэкап — можно удалить смело;
- единственной сохранённой версией базы до миграции полугодовой давности, о которой никто, кроме этого файла, не помнит;
- частью самодельного скрипта, который складывает дампы на этот же диск — тогда удаление одного файла ничего не решит, завтра накопится новый.
Практическая проверка — сравнить дату дампа с датой последнего изменения таблиц в реальной базе и посмотреть, ссылается ли на этот путь какой-нибудь cron или systemd-таймер:
crontab -l
for u in $(cut -f1 -d: /etc/passwd); do crontab -u $u -l 2>/dev/null; done
systemctl list-timers --all
grep -rl "/path/to/dump" /etc/cron.d /etc/systemd/system 2>/dev/null
Если скрипт, который пишет дампы в этот каталог, всё ещё активен — сначала чините ротацию (пусть держит последние N копий), и только потом чистите накопившееся. Если разбираете доставшийся по наследству сервер целиком, а не только диск, общий порядок аудита описан в статье «Сервер достался по наследству: проверка чужой машины перед боем» — там про доступы, cron и открытые порты, диск лишь часть картины.
Проверьте и дублирование бэкапов между локальным диском и внешним хранилищем: если дампы синхронизируются в S3-совместимое хранилище или на другой сервер, локальная копия старше нескольких дней обычно избыточна.
Что выглядит мусором, но держит систему
Это самая опасная часть разборки: файлы и каталоги, которые визуально ничем не отличаются от мусора, но их удаление обрывает работающий сервис немедленно или отложенно.
Unix-сокеты активных сервисов. /var/run/docker.sock, /var/run/mysqld/mysqld.sock, /var/run/postgresql/.s.PGSQL.5432 — с виду файлы нулевого размера, но через них процессы общаются друг с другом прямо сейчас. Удаление не освободит место (они почти ничего не весят), но сломает связь клиента с сервисом до перезапуска демона.
Файлы блокировок. .lock, .pid в /var/run и /run/lock — тоже почти невесомы, но их наличие иногда проверяют скрипты и systemd-юниты перед стартом. Удалять их вручную стоит, только когда точно знаете, что владеющий процесс мёртв — иначе рискуете получить два одновременно запущенных экземпляра сервиса, рассчитывавшего на единственность.
Точки монтирования. Пустой на вид каталог /mnt/old-storage может быть точкой монтирования отвалившегося сетевого диска. Если файловая система туда не примонтирована в момент проверки, du покажет пустоту — а по факту под точкой монтирования на локальном диске может лежать старое содержимое, скрытое смонтированным поверх томом, когда он на месте. Проверяйте:
mount | grep <путь>
cat /proc/mounts | grep <путь>
Если каталог значится как точка монтирования в /etc/fstab, но сейчас не смонтирован — не удаляйте и не пересоздавайте его бездумно, сначала выясните, должен ли том вернуться на место.
Удалённые, но открытые файлы. Классическая ловушка наоборот: вы удаляете огромный лог командой rm, df -h показывает, что место не освободилось, и кажется, что что-то сломалось. На самом деле всё штатно — если файл был открыт процессом на запись, ядро Linux хранит данные на диске, пока хотя бы один дескриптор на него открыт. Место освободится, только когда процесс закроет файл или перезапустится. Найти такие «висящие» файлы:
lsof +L1 2>/dev/null | grep -v COMMAND
Столбец с числом ссылок покажет 0 — это и есть удалённый, но ещё занимающий место файл. Решение — не трогать руками файловую систему, а мягко перезапустить процесс, который его держит (systemctl restart <service>), либо дождаться планового рестарта.
Слои Docker-образов, на которые ссылаются остановленные контейнеры. Контейнер в состоянии Exited всё ещё держит свой образ и файловое дерево на диске — это не забытый мусор, а сохранённое состояние (например, чтобы посмотреть логи упавшего контейнера). docker container prune уберёт такие контейнеры, но сначала убедитесь, что их падение уже разобрано — иначе теряете диагностику.
Таблица-шпаргалка для быстрой сверки:
| Находка | Обычно можно удалить | Сначала проверить |
|---|---|---|
*.gz в /var/log старше 90 дней | да | требования по хранению логов |
| Кэш apt/dnf/npm/pip | да | — |
| journald без лимита | да, через --vacuum-size | нужен ли долгий аудит-лог |
| Старые ядра, кроме двух последних | да | грузится ли текущее |
| Docker build cache | обычно да | активные CI-пайплайны |
| Docker-образы без контейнера | осторожно | контейнеры по расписанию (cron) |
| Ручные дампы БД | зависит | есть ли автоматический бэкап-скрипт |
Unix-сокеты, .lock/.pid | нет, почти невесомы | сами по себе не экономят место |
| Точки монтирования | нет | должен ли том быть смонтирован |
| Удалённый, но открытый файл | место не освободится через rm | нужен рестарт держащего процесса |
Порядок действий: от безопасного к рискованному
Разборка забитого диска — не одна команда, а последовательность шагов с проверкой после каждого. Рекомендуемый порядок:
- Снимок состояния.
df -h,du -x --max-depth=1по дереву, вывод в файл — точка отсчёта, к которой вы будете возвращаться. - Мониторинг на время работы. Если на сервере ещё нет наблюдения за диском, поставьте его прямо сейчас, прежде чем начинать чистку — так вы увидите эффект от каждого шага и заметите, если после рестарта сервиса место вдруг снова начнёт уходить.
- Безусловно безопасное. Кэши пакетных менеджеров, journald с лимитом, ротированные логи старше согласованного срока хранения.
- Docker-хозяйство с ручной проверкой. Сначала
docker system df -vи просмотр списков глазами, потом точечная чистка, а неprune -a --volumesодной командой по всей системе. - Дампы и архивы — только после сверки с cron/systemd-таймерами и датой последнего изменения реальных данных.
- Ничего из раздела «держит систему» не трогается вообще, пока не разобрано, что конкретно к этому файлу или каталогу привязано.
- Контрольный df -h после каждого крупного шага, а не один раз в конце — так проще понять, какой именно шаг дал эффект, и откатиться мысленно, если что-то пошло не так.
Возьмите за привычку не удалять сразу, а сначала переносить сомнительное в отдельный каталог с говорящим именем (/root/to-delete-2026-08/) и оставлять на пару дней — если ничего не сломалось и никто не хватился файла, можно удалять с чистой совестью. Это стоит лишних мегабайт временно, зато отменяемо.
Если после чистки диск всё равно впритык под реальный рабочий объём данных — это не повод резать по живому дальше, а сигнал, что заказанный том маловат для текущей нагрузки. Расширить диск на работающем сервере обычно можно без простоя, если позволяет платформа — подробности в статье «Как расширить диск на работающем сервере».
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
С чего начать, если сервер уже на 100% и сервисы падают прямо сейчас?
Экстренно освободите минимум через journalctl --vacuum-size и apt-get clean — это безопасно и быстро даёт достаточно, чтобы сервисы снова могли писать логи и временные файлы. Полную разборку по разделам этой статьи проводите уже после того, как острая фаза снята.
Можно ли просто снести весь /var/lib/docker и переустановить Docker с нуля?
Технически да, но вы потеряете все образы, тома с данными контейнеров и сети — если есть контейнеры с состоянием (базы данных, файловые хранилища), это фактически удаление продакшен-данных. Делайте это только после инвентаризации, что в docker volume ls действительно бэкапится, а что нет.
du и df показывают разные цифры занятого места — почему?
Классический признак удалённых, но открытых файлов. du считает по файлам, видимым в дереве каталогов, df — по фактически занятым блокам, включая невидимые открытые файлы. Расхождение в несколько гигабайт — сигнал искать процесс через lsof +L1.
Как понять, что дамп базы можно удалить, если старый администратор недоступен?
Сверьте дату дампа с датой последних изменений в реальной базе (SHOW TABLE STATUS для MySQL, pg_stat_user_tables для PostgreSQL) и проверьте, ссылается ли на этот файл действующий cron или systemd-таймер. Если дамп старше всех правок в данных на порядок и ни один процесс на него не смотрит — почти наверняка забытая копия.
Стоит ли доверять инозулам (df -i) так же, как месту в байтах?
Да, и это отдельная проблема — миллионы мелких файлов (сессии PHP, кэши) могут исчерпать инозулы при свободных гигабайтах места. Ищите виновника через find <каталог> | wc -l, а не через du.
Что делать, если после чистки диск снова забивается за несколько дней?
Значит, дело не в накопленном мусоре, а в активном процессе, который продолжает писать — логировании без ротации, самопишущем скрипте бэкапа без лимита хранения или утечке в приложении. Разовая чистка такую причину не устраняет, нужно найти и ограничить источник.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →