Главная » Диски и файловые системы » Закончилось место на диске сервера: как найти, что занимает место

Закончилось место на диске сервера: как найти, что занимает место

Сайт вдруг отдаёт ошибку 500, в админку не войти, база данных перестала сохранять изменения, а в логах — No space left on device. На сервере закончилось место. Обычно это не внезапная беда, а результат месяцев накопления: логов, резервных копий, кэша, которые никто не чистил.

Коротко: посмотрите df -h и df -i, затем найдите крупные каталоги через du или ncdu, не уходя на другие разделы. Если df показывает, что диск занят, а du столько не находит, — место держат удалённые, но ещё открытые файлы. Активные логи не удаляйте, а обнуляйте, и сразу настройте ограничения, чтобы ситуация не повторилась.

Как проявляется нехватка места

Симптом Что это значит Что делать
No space left on device при записи, df -h показывает 100% Закончилось место на разделе Найти крупные каталоги через du или ncdu
Та же ошибка, но в df -h место есть Закончились inode — слишком много мелких файлов Проверить df -i, найти каталог с файлами
df показывает занятое место, du его не находит Удалённые файлы ещё держит открытыми какой-то процесс lsof +L1, перезапустить процесс или обнулить файл
Сайт отдаёт 500, MySQL или MariaDB не сохраняет данные или не запускается Базе данных и PHP некуда писать временные файлы, сессии, журналы Освободить место, затем проверить журнал ошибок базы
В error.log nginx — (28: No space left on device) или логи перестали пополняться Веб-серверу некуда писать логи и временные файлы Освободить место, переоткрыть логи nginx -s reopen

По документации MySQL, при заполненном диске сервер раз в минуту проверяет, не освободилось ли место, и раз в десять минут пишет предупреждение в журнал ошибок. Запись при этом ждёт — сайт выглядит «зависшим» (подробнее в разделе How MySQL Handles a Full Disk).

Первая минута: df -h и df -i

df -h
Filesystem      Size  Used Avail Use% Mounted on
udev            1.9G     0  1.9G   0% /dev
tmpfs           392M  628K  391M   1% /run
/dev/vda1        40G   38G     0 100% /
tmpfs           2.0G     0  2.0G   0% /dev/shm
/dev/vda15      124M   12M  113M  10% /boot/efi

Смотрите на реальные разделы, а не на tmpfs — это память. Если Used меньше Size, а Avail уже ноль, это не ошибка: на ext4 часть блоков по умолчанию (5%) зарезервирована для root. Поэтому службы, работающие от root, ещё какое-то время пишут, а сайты от обычных пользователей уже нет.

Вторая обязательная проверка — inode, то есть количество файлов:

df -i
Filesystem      Inodes   IUsed IFree IUse% Mounted on
/dev/vda1      2621440 2621440     0  100% /

При 100% в IUse% новый файл не создать, даже если гигабайты свободны. Число inode на ext4 задаётся при создании файловой системы, и настройкой его не увеличить — помогает только удаление лишних файлов.

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

Где именно занято место

du: по каталогам, сверху вниз

du -xh --max-depth=1 / 2>/dev/null | sort -h
16K	/lost+found
7.6M	/etc
212M	/root
1.9G	/usr
3.1G	/var
32G	/home
38G	/

Ключ -x не даёт уходить на другие файловые системы — иначе в подсчёт попадут /proc, сетевые и смонтированные диски. Дальше повторяете команду для самого большого каталога: du -xh --max-depth=1 /home | sort -h, и так до виновника.

Для поиска отдельных больших файлов:

find / -xdev -type f -size +500M -exec ls -lh {} + 2>/dev/null

ncdu: то же самое, но удобнее

ncdu -x /

Программа один раз сканирует диск и показывает интерактивный список: стрелками заходите в каталоги, d удаляет выбранное (с подтверждением), q — выход. Ставится из основных репозиториев Debian и Ubuntu (apt install ncdu), в AlmaLinux — из EPEL. Если места ноль, установить её может не получиться — тогда хватит du.

Если не хватает inode

Ищите каталог, где больше всего файлов:

du --inodes -x --max-depth=1 / 2>/dev/null | sort -n | tail

Чаще всего это сессии PHP, кэш сайтов в виде тысяч мелких файлов, очередь почты или каталог, куда скрипт годами складывает временные файлы.

Удалённые, но открытые файлы

Классическая ситуация: большой лог удалили через rm, а место не освободилось. Файл исчез из каталога, но процесс, который в него пишет, держит его открытым, и данные остаются на диске, пока процесс не закроет файл.

lsof +L1
COMMAND  PID     USER   FD   TYPE DEVICE   SIZE/OFF NLINK   NODE NAME
nginx   1187 www-data    5w   REG  254,1 6442450944     0 393251 /var/log/nginx/access.log.1 (deleted)

+L1 выводит файлы, у которых не осталось ни одного имени в файловой системе. Если lsof не установлен, то же покажет find /proc/*/fd -ls 2>/dev/null | grep deleted.

Освободить место можно двумя способами: перезапустить или попросить переоткрыть файлы сам процесс (для nginx — nginx -s reopen или systemctl reload nginx), либо обнулить файл через его дескриптор:

truncate -s 0 /proc/1187/fd/5

Где обычно копится

Логи и журнал systemd

du -sh /var/log/* 2>/dev/null | sort -h | tail
journalctl --disk-usage
Archived and active journals take up 3.9G in the file system.

Журнал systemd по умолчанию может занимать до 10% файловой системы (но не больше 4 ГБ). Сократить сразу:

journalctl --vacuum-size=500M

и закрепить лимит в файле /etc/systemd/journald.conf.d/size.conf (описание параметров — в man journald.conf):

[Journal]
SystemMaxUse=500M

После этого — systemctl restart systemd-journald. В Debian 12 и 13 rsyslog по умолчанию не ставится, поэтому основной системный лог — именно журнал. Сжатые старые логи (*.gz, *.1) в /var/log можно удалять. А вот текущий лог, в который пишет служба, только обнуляйте:

truncate -s 0 /var/log/nginx/error.log

Кэши пакетов и старые ядра

# Debian, Ubuntu
apt clean
apt autoremove --purge

# AlmaLinux, Rocky
dnf clean all
dnf remove --oldinstallonly

apt autoremove убирает ненужные зависимости, включая старые ядра. dnf remove --oldinstallonly удаляет старые ядра, оставляя последние и текущее работающее; сколько хранить, задаёт installonly_limit в /etc/dnf/dnf.conf (по умолчанию 3).

Бэкапы, дампы и архивы

Самая частая находка — резервные копии и дампы баз в /root, /home, /var/backups или прямо в каталоге сайта: backup.tar.gz, site_old.zip, db-2025.sql. Заодно проверьте, нет ли копий в публичном каталоге сайта: их могут скачать посторонние.

Если включены бинарные логи MySQL (в MySQL 8.0 и 8.4 они включены по умолчанию), не удаляйте файлы binlog.* вручную — используйте команду сервера:

PURGE BINARY LOGS BEFORE NOW() - INTERVAL 3 DAY;

Кэш страниц сайтов

Плагины кэширования (у WordPress — каталог wp-content/cache) и fastcgi_cache nginx могут разрастаться без предела. Для nginx задайте max_size в fastcgi_cache_path, для плагинов — срок жизни кэша.

Docker

docker system df
TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          14        5         9.214GB   6.871GB (74%)
Containers      7         5         1.032GB   0B (0%)
Local Volumes   6         4         3.5GB     812.4MB (23%)
Build Cache     41        0         2.106GB   2.106GB

docker system prune удаляет остановленные контейнеры, неиспользуемые сети, «висячие» образы и кэш сборки; с -a — все неиспользуемые образы. Ключ --volumes без понимания, что лежит в томах, не используйте — там могут быть данные. Ещё один источник — логи контейнеров: у драйвера json-file по умолчанию нет ограничения размера, его задают через log-opts (max-size, max-file) в /etc/docker/daemon.json. Новые настройки действуют только на контейнеры, созданные после перезапуска Docker.

Как освобождать безопасно

Если сервер нужно вернуть к жизни прямо сейчас, начните с того, что точно ничего не сломает: сократите журнал systemd, удалите сжатые старые логи и почистите кэш пакетов. Обычно это даёт достаточно места, чтобы заработали база данных и сайт, а дальше можно спокойно разбираться с главной причиной.

journalctl --vacuum-size=200M
find /var/log -type f -name '*.gz' -delete
apt clean    # или dnf clean all

Дальше несколько правил, которые я соблюдаю при любой чистке:

  • Не удаляйте активные логи — обнуляйте их через truncate -s 0. Удалённый лог продолжит занимать место, пока служба его не закроет.
  • Не трогайте вручную /var/lib/mysql, /var/lib/docker, /var/lib/dpkg, /var/lib/rpm: такие каталоги чистятся только средствами самих программ.
  • Прежде чем удалять бэкап, убедитесь, что его копия есть в другом месте.
  • Освободив место, перезапустите службы, которые падали: базу данных, PHP-FPM, веб-сервер. Проверьте журнал ошибок базы: операции, прерванные нехваткой места, могут оставить таблицы в неисправном состоянии.

Бывает и обратная ситуация: Apache пишет No space left on device, хотя место есть и inode тоже. Это нехватка семафоров, а не диска — разбор в статье Apache: No space left on device: Couldn’t create accept lock.

Типичная история

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

Место быстро освобождается удалением старых архивов, но настоящих исправлений два. Первое — копии должны уходить на отдельный сервер: копия на том же диске не спасёт ни от отказа диска, ни от потери сервера целиком. Второе — ротация с ограничением числа копий, чтобы хранилище не росло бесконечно. Простейший вариант — оставлять семь последних архивов:

ls -1t /backup/site-*.tar.gz | tail -n +8 | xargs -r rm --

Как копировать файлы между серверами, описано в статье scp, sftp и rsync.

Как не допустить повторения

  • Мониторинг свободного места и inode с уведомлением на 80–85% — заранее, а не по жалобам посетителей.
  • Ограничение журнала systemd (SystemMaxUse) и проверка logrotate для логов сайтов: logrotate -d /etc/logrotate.conf покажет, что будет сделано, ничего не меняя.
  • Бэкапы — на другой сервер или в отдельное хранилище, с ротацией.
  • Лимиты для кэшей и логов Docker.
  • Раз в месяц — du -xh --max-depth=1 / | sort -h, чтобы видеть, что растёт.

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

Удалил большие файлы, а df показывает то же самое. Почему?

Файлы держит открытыми какой-то процесс. Найдите его через lsof +L1 и перезапустите службу или обнулите файл через /proc/<PID>/fd/<номер>. Пока процесс держит файл, место не освободится.

Места полно, но пишет No space left on device. Что это?

Чаще всего закончились inode — проверьте df -i. Если и там свободно, причина может быть не в диске: например, Apache так же сообщает о нехватке семафоров. Ещё вариант — квота пользователя на хостинге.

Можно ли просто удалить все логи в /var/log?

Нет. Старые сжатые логи удалять можно, текущие лучше обнулять через truncate -s 0. Журнал systemd чистится только через journalctl --vacuum-size или --vacuum-time, а не удалением файлов.

Почему в Debian 13 tmp занимает память, а не диск?

Начиная с Debian 13, каталог /tmp по умолчанию находится в tmpfs — в памяти, до 50% её объёма. Временные файлы там не занимают диск, но расходуют оперативную память, и после перезагрузки исчезают.