MAATRIX / Блог / Ежеквартальная уборка диска: старые бэкапы, логи, образы и забытые архивы

Ежеквартальная уборка диска: старые бэкапы, логи, образы и забытые архивы

MAATRIX

Диск на рабочем сервере почти никогда не заполняется одним большим файлом за один день. Он забивается медленно: бэкап, который скрипт ротации перестал чистить полгода назад, лог, который логротейт не сжимает из-за опечатки в конфиге, образ Docker, оставшийся от эксперимента в марте. По отдельности каждый такой файл не тревожит мониторинг — рост слишком плавный. А раз в квартал вы открываете df -h и видите 91% на разделе, который год назад был заполнен на треть. Ниже — конкретный список категорий такого мусора, команды, чтобы его найти, и правило, которое убережёт от удаления чего-то нужного.

Почему это отдельная задача, а не часть ежедневного мониторинга

У обслуживания диска три разных горизонта, и смешивать их — плохая идея. Ежедневный мониторинг ловит пороги: диск подошёл к 85–90%, алерт сработал, кто-то среагировал. Это подробно разобрано отдельно на случай, когда место уже кончилось — там счёт идёт на минуты, и задача не «прибраться», а срочно найти виновника и остановить деградацию. Еженедельный регламент, если он у вас настроен по отдельному чек-листу на 40 минут, смотрит на тренд: диск растёт на 1–2% в неделю — это нормально или нет. Но ни один из этих горизонтов не задаёт вопрос «а зачем вообще лежит вот этот файл 40-гигабайтный архив от миграции, которую делали в январе?» — потому что он не растёт, не превышает порог и не участвует в тренде. Он просто лежит и медленно съедает запас, который вы могли бы использовать для роста нагрузки.

Ежеквартальная уборка — это единственный момент, когда кто-то целенаправленно проходит по диску и задаёт вопрос «а это точно ещё нужно» для каждого крупного объекта, а не только для того, что превысило порог алерта. На малых VPS с одним диском под систему и данные это можно сделать за 30–40 минут. На серверах с несколькими смонтированными разделами под бэкапы, логи и данные — закладывайте час-полтора, особенно в первый раз, когда накопления никто не разбирал.

Составляем карту диска: с чего начать поиск

Прежде чем что-то трогать, нужна картина: какие разделы заполнены и что внутри них весит больше всего. Начните с обзора разделов:

df -h

Дальше — спуск по дереву каталогов от корня, чтобы увидеть крупные директории на верхнем уровне:

du -h --max-depth=1 / 2>/dev/null | sort -hr | head -20

Если какой-то каталог оказался тяжёлым (часто это /var, /home, /opt или точка монтирования под данные), повторите команду уже внутри него, увеличивая глубину постепенно — сразу лезть на --max-depth=5 в корень бессмысленно, вывод превращается в кашу:

du -h --max-depth=2 /var 2>/dev/null | sort -hr | head -20

Отдельно полезно найти именно крупные файлы, а не каталоги — иногда виновник не директория, а один забытый дамп в /root:

find / -xdev -type f -size +200M 2>/dev/null -exec du -h {} \; | sort -rh | head -30

Флаг -xdev не даёт команде уйти на смонтированные сетевые шары или другие файловые системы — без него поиск может зависнуть на медленной точке монтирования. Если сервер большой и по нему приходится ходить регулярно, поставьте ncdu — интерактивный аналог du с навигацией стрелками, который сильно экономит время на второй и третий квартал:

apt install ncdu   # или: dnf install ncdu
ncdu /

Держите этот шаг первым каждый раз: карта диска у вас в руках, дальше — по категориям.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Категория 1: бэкапы за пределами срока хранения

Это самый частый источник тихо накопленного мусора. Скрипт бэкапа настраивали два года назад, retention прописали «на глаз», потом сменился формат хранения, добавился ещё один инструмент бэкапа — а старый не выключили. В итоге на диске одновременно лежат архивы от старого и нового механизма.

Ориентир по срокам хранения, от которого можно отталкиваться при ревизии (для вашего проекта цифры могут быть другими — это не универсальный стандарт, а отправная точка для разговора с командой):

Тип копииТипичный срок храненияГде проверить
Ежедневная7–14 днейлокальный каталог бэкапов
Еженедельная4–8 недельлокально или offsite
Ежемесячная6–12 месяцевoffsite/холодное хранилище
Годоваяпо требованиям (часто бессрочно)offsite

Найдите бэкапы старше разумного срока в локальном каталоге:

find /var/backups -type f -mtime +90 -name "*.tar.gz" -exec ls -lh {} \;

Замените маску и путь на реальные для вашего проекта — у постгреса это обычно *.sql.gz или *.dump, у файловых бэкапов *.tar.zst или *.tar.gz. Если для бэкапов используется restic или borgbackup, не удаляйте архивы руками — у них своя логика хранения снапшотов с дедупликацией, и ручное rm может сломать цепочку. Посмотрите, что реально лежит, и почистите штатной командой:

restic snapshots
restic forget --keep-daily 14 --keep-weekly 8 --keep-monthly 12 --prune

# для borgbackup:
borg list /path/to/repo
borg prune --keep-daily 14 --keep-weekly 8 --keep-monthly 12 /path/to/repo

Отдельно проверьте, не копится ли параллельно и старый механизм бэкапа, который уже никто не использует, но который никто не выключил — это встречается едва ли не чаще, чем превышение retention у актуального. И главное правило: прежде чем удалять старую копию бэкапа — убедитесь, что более свежая копия реально существует и валидна (хотя бы tar tzf archive.tar.gz > /dev/null без ошибок), а не просто «должна была создаться по расписанию».

Категория 2: ротированные логи, которые никто не сжал

Логротейт стоит почти везде из коробки, и именно поэтому на него перестают смотреть — а зря: опечатка в конфиге, сервис, который не подхватывает postrotate, или директива compress, которую забыли добавить при настройке нового приложения, превращают ротацию в простое переименование файлов без экономии места.

Оцените, что весит больше всего в /var/log:

du -sh /var/log/* 2>/dev/null | sort -rh | head -20

Найдите ротированные, но не сжатые файлы — если логротейт настроен верно, такие после первого цикла ротации уже должны быть в .gz:

find /var/log -name "*.log.[0-9]*" ! -name "*.gz" -mtime +7

Если находите много таких — загляните в конфиг конкретного сервиса в /etc/logrotate.d/ и проверьте на нём директиву compress, а заодно прогоните логротейт в тестовом режиме, чтобы увидеть, что он реально будет делать:

logrotate -d /etc/logrotate.d/nginx

Отдельная категория — журнал systemd, который логротейт вообще не трогает, у него свой лимит:

journalctl --disk-usage
journalctl --vacuum-time=90d
# или ограничить по размеру:
journalctl --vacuum-size=500M

И классическая грабля, которую находит именно квартальная уборка, а не еженедельная: процесс держит открытым файл, который уже удалён с диска, но место под него не освобождается, пока процесс не перезапущен. du такой файл не покажет вообще, а df покажет занятое место — отсюда расхождение, которое сбивает с толку. Найти это можно так:

lsof +L1 2>/dev/null | grep -i deleted

Если видите там гигабайты под каким-нибудь nginx или логирующим агентом — решение не «удалить», а корректно перезапустить процесс (или отправить ему сигнал на переоткрытие файлов, если приложение это поддерживает), после чего место освободится само.

Категория 3: старые Docker- и VM-образы

На серверах с Docker место уходит незаметно быстрее всего: каждая пересборка оставляет промежуточные слои, каждый docker pull новой версии образа не удаляет старую автоматически. Разбор именно этой проблемы — и подробные команды по каждой категории — есть в отдельной статье, здесь — квартальный минимум.

Сначала посмотрите общую картину по категориям:

docker system df -v

Отдельно список образов с датой создания — так проще увидеть, что действительно старое:

docker image ls -a --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}\t{{.CreatedSince}}"

Безопасная уборка неиспользуемого — того, что не привязано ни к одному контейнеру:

docker system prune -a --filter "until=2160h"

Фильтр until=2160h (90 дней) не даёт снести образ, который вы просто давно не запускали, но собираетесь использовать на следующей неделе — без фильтра -a удалит вообще всё, что не используется прямо сейчас, включая то, что вы через два дня будете заново качать или собирать. Перед прогоном на боевом сервере полезно сначала посмотреть, что попадёт под удаление, добавив --dry-run в некоторых версиях Docker, либо просто внимательно прочитать список, который команда покажет и попросит подтвердить.

Если на сервере крутятся виртуальные машины через libvirt/KVM, образы и снапшоты стоит проверять отдельно — они не подчиняются Docker-командам:

du -sh /var/lib/libvirt/images/*
qemu-img info /var/lib/libvirt/images/имя-диска.qcow2

qemu-img info покажет виртуальный размер диска и реально занятое место — если разница огромная, возможно, стоит выполнить qemu-img convert в новый файл для дефрагментации разреженного образа, но это отдельная операция, требующая остановки VM и отдельного планирования, не для квартальной уборки на бегу.

Категория 4: забытые архивы миграций и дебаг-дампы

Эта категория почти никогда не попадает под автоматическую очистку, потому что у неё нет расписания и нет владельца — файл создали руками во время разовой задачи и забыли.

Типичные примеры: полный tar старых данных, снятый «на всякий случай» перед миграцией на новый сервер и оставленный лежать на новом сервере после того, как переезд подтвердили успешным; дамп базы, снятый прямо перед рискованной операцией и забытый в домашней директории; выгрузка для дебага прод-инцидента полугодовой давности, которую скачивали для анализа локально, да так и не удалили с сервера.

Найти такие файлы помогает поиск по расширениям в нетипичных для них местах — домашних директориях, /root, /tmp:

find /root /home -maxdepth 3 -type f \( -iname "*.sql" -o -iname "*.sql.gz" -o -iname "*.dump" -o -iname "*.tar" -o -iname "*.tar.gz" \) -mtime +90 -exec ls -lh {} \;

Отдельно проверьте /tmp и /var/tmp — по умолчанию файлы там не живут вечно (за очистку часто отвечает systemd-tmpfiles или планировщик), но если правила очистки для конкретного каталога не настроены, старые дебаг-выгрузки могут копиться годами:

find /tmp /var/tmp -type f -mtime +30 -exec ls -lh {} \;

Если находите что-то похожее на разовую выгрузку без понятного владельца — не удаляйте сразу, а сначала откройте и посмотрите содержимое (less, zcat file.sql.gz | head -50, tar tzf archive.tar.gz | head), чтобы понять, что это и когда создано, и при возможности спросите в команде, помнит ли кто-то этот файл.

Безопасный подход: сначала смотрите, а потом удаляете

Главный риск ежеквартальной уборки — не в том, что вы не найдёте мусор, а в том, что удалите что-то нужное, потому что торопились и полагались на маску по расширению или дате, не заглянув внутрь. Рабочий порядок:

  1. Найдите и составьте список. Команды выше дают список кандидатов с путями и размерами — не удаляйте по ходу поиска, сначала соберите полную картину.
  2. Откройте и проверьте каждый крупный объект. less, zcat ... | head, tar tzf, docker image inspect — минута на файл экономит часы на восстановление, если ошиблись.
  3. Проверьте, что файл не используется прямо сейчас. lsof <путь> покажет, держит ли его открытым какой-то процесс; для конфигов и путей, зашитых в другие сервисы, — простой grep -r "имя_файла" /etc /opt не будет лишним.
  4. Переносите в карантин, а не удаляйте сразу. Вместо rm -rf на подозрительный, но не до конца понятный объект — переместите его в отдельный каталог с датой и подождите:
mkdir -p /var/quarantine-2026q3
mv /home/user/old_migration_dump.sql.gz /var/quarantine-2026q3/

Через одну-две недели, если никто не хватился и ничего не сломалось, каталог карантина можно удалить целиком — это гораздо безопаснее, чем удалять напрямую в момент находки, особенно в первый квартал уборки, когда вы ещё не знаете всех особенностей конкретного сервера.

  1. Ведите короткий журнал того, что почистили. Дата, что удалили, сколько места освободили — простой текстовый файл или запись в тикет-трекере. Это не бюрократия ради галочки: через год такой журнал покажет, растёт ли объём мусора быстрее, чем раньше, и не стоит ли пересмотреть retention бэкапов или добавить автоматическую очистку в конкретном месте вместо ручной уборки каждый квартал.

И отдельно: если чистите именно бэкапы — убедитесь, что у вас в принципе есть актуальная резервная копия важных данных где-то ещё, прежде чем удалять старые архивы «за ненадобностью». Уборка диска не должна оставить вас без единственной сохранившейся копии чего-то важного.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Раз в квартал — это обязательно, или можно реже?

Для маленького одиночного VPS с редкими деплоями можно раз в полгода — накопление там медленнее. Для серверов с активной разработкой, частыми деплоями и Docker-сборками раз в квартал — разумный минимум, иначе мусора накапливается на несколько часов разбора вместо 30–40 минут.

Можно ли просто написать cron-скрипт, который удаляет всё старше N дней по маске?

Для предсказуемых категорий вроде логов старше 90 дней или дебаг-дампов в /tmp — да, это разумно автоматизировать. Для бэкапов и архивов миграций — осторожно: слепое удаление по дате может снести единственную сохранившуюся копию чего-то, что просто давно не трогали, но оно нужно. Такие категории лучше оставлять на ручную проверку раз в квартал.

Диска не хватает прямо сейчас, ждать до плановой уборки нельзя — что делать?

Это уже не квартальная уборка, а срочный разбор — смотрите отдельный разбор ситуации, когда место на VPS уже кончилось: там порядок действий заточен под скорость, а не под системность.

Как понять заранее, сколько места реально освободится, не удаляя?

Для каталога — du -sh /path/to/dir перед удалением. Для Docker — docker system df покажет RECLAIMABLE по каждой категории ещё до prune. Всегда полезно свериться с df -h до и после, а не полагаться только на размер удалённого объекта — иногда файловая система освобождает место не мгновенно.

Стоит ли использовать готовые утилиты для автоматической очистки системы?

Такие инструменты неплохо ловят типовой системный мусор (кэш пакетного менеджера, старые ядра), но для специфичных для вашего проекта категорий — бэкапов, дампов, архивов миграций — они не знают контекста и не заменяют осмысленную ручную проверку раз в квартал.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →