Выберите продукт

Linux ENOSPC из-за inode: диагностика df -i и быстрые способы исправления

ENOSPC «No space left on device» появляется даже при свободных гигабайтах, если закончились inode. Разберём проверку df -i, поиск каталога-источника через findmnt и find, безопасную очистку (логи, tmp, Docker overlay2) и профилактику: retention и мониторинг.
Linux ENOSPC из-за inode: диагностика df -i и быстрые способы исправления

Почему ENOSPC бывает при свободных гигабайтах

Ошибка ENOSPC («No space left on device») не всегда означает, что закончились блоки (ёмкость) на диске. В Linux есть второй лимит: количество inode (индексных дескрипторов). Почти каждый объект в файловой системе (файл, каталог, симлинк, сокет) потребляет один inode. Если inode кончились, создать новый файл нельзя, даже если по df -h ещё остаются гигабайты.

Типичная картина: приложение не может писать кэш/сессии, почта не принимает письма, база не создаёт временные файлы, ротация логов ломается, Docker не распаковывает слои. В логах при этом встречаются сообщения вида ENOSPC и упоминания inodes.

Практическое правило: «место закончилось» в Linux может означать блоки, inode или квоты. Здесь разбираем именно случай, когда упёрлись в inode.

Быстрая проверка: df -i и что смотреть в выводе

Начните с проверки inode на всех смонтированных ФС:

df -i

Смотрите колонки IUsed, IFree, IUse%. Если на нужном маунте IUse% близко к 100% (или IFree около нуля), это и есть причина «нет места» при видимом свободном объёме.

Для сравнения проверьте объём:

df -h

Если по df -h свободно, а по df -i inode закончились, значит нужно искать каталоги с огромным количеством мелких объектов.

Как понять, что упёрлись именно в inode

  • создание временных файлов падает (кэш, сессии, загрузки);
  • logrotate не может создать новый файл;
  • почтовые сервисы не создают файлы очереди;
  • apt/dnf не распаковывает пакеты;
  • Docker ругается на распаковку/слои (часто на overlay2).

Где чаще всего «утекают» inode: практические кейсы

1) Логи и log spam мелкими файлами

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

Проверьте в первую очередь:

  • /var/log и вложенные каталоги;
  • кастомные каталоги логов (часто /srv, /opt, /home);
  • папки с некорректной ротацией (например, «лес» файлов по шаблону).

2) /tmp, /var/tmp и временные каталоги приложений

Если /tmp расположен на обычном дисковом разделе (не tmpfs) или приложение пишет временные файлы не в /tmp, а в свою папку, мусор может копиться неделями. Особенно опасны сценарии «тысячи мелких файлов» и отсутствие очистки при аварийном завершении.

Правильное решение обычно включает понятный TTL/retention и автоматическую очистку (например, через systemd-tmpfiles), а не «ручную уборку по праздникам».

Чтобы подобные инциденты не превращались в «пожар на весь сервер», удобно выносить шумные каталоги (логи, кэши, Docker data root) на отдельные тома или отдельную машину. Если проект растёт, часто проще перейти на VDS и разнести нагрузку по дискам, чем постоянно ужиматься в одном разделе.

FastFox VDS
Облачный VDS-сервер в России
Аренда виртуальных серверов с моментальным развертыванием инфраструктуры от 195₽ / мес

3) Docker: overlay2 и «миллионы маленьких» в слоях

Частый инцидент — docker overlay2 inodes. Контейнеры могут занимать немного места по объёму, но содержать очень много файлов (например, node_modules, кэши пакетных менеджеров, build-артефакты). Если /var/lib/docker лежит на разделе с ограниченным числом inode (особенно на ext4), inode могут закончиться неожиданно быстро.

Уточните, где Docker хранит данные:

docker info

Дальше проверьте inode именно на том маунте, где находится Docker data root, через df -i.

Если активно используете контейнеры в проде, пригодится отдельная статья про контейнерную песочницу и изоляцию: усиление изоляции контейнеров (gVisor/Firecracker).

Схема диагностики нехватки inode: df -i и поиск проблемного маунта

4) Особенности ФС: ext4 и XFS

На ext4 число inode обычно задаётся при создании файловой системы. В «обычном» сценарии вы не можете просто так «добавить inode» на существующую ext4 без миграции/пересоздания. Поэтому ситуация «inode закончились» на ext4 встречается часто, если раздел изначально проектировали под несколько крупных файлов, а затем начали хранить кэши и контент из миллионов объектов.

В XFS inode создаются динамически, поэтому упереться именно в inode сложнее, но неконтролируемый рост количества файлов всё равно приведёт к проблемам (пусть и иного характера). Практическая мысль одна: лечить нужно причину появления миллионов объектов, а не только последствия.

Как быстро найти, где сожрали inode

Цель — найти каталоги с максимальным числом объектов внутри конкретной файловой системы, где кончились inode. Важно: подсчёт файлов на миллионах объектов может быть долгим и тяжёлым по диску, поэтому идите от общего к частному.

Шаг 1: определить проблемный маунт

df -i
findmnt -T /var/log
findmnt -T /var/lib/docker
findmnt -T /tmp

findmnt -T показывает, на каком разделе находится путь. Искать «пожирателя» нужно именно там, где у вас IUse% близко к 100%.

Шаг 2: прикинуть, кто виноват на верхнем уровне

Если проблемный раздел смонтирован в /var, начните с верхнего уровня и используйте -xdev, чтобы не уходить на другие файловые системы:

cd /var
for d in *; do echo "$d $(find "$d" -xdev -mindepth 1 -print 2>/dev/null | wc -l)"; done | sort -n

Команда может выполняться заметно долго, но обычно даёт быстрый ориентир: какой каталог «вырвался вперёд» по количеству объектов.

Шаг 3: углубляться до конкретной папки

Дальше повторяйте тот же приём внутри лидирующего каталога, пока не дойдёте до конкретного места, где копятся сотни тысяч или миллионы файлов. После этого у вас будет предметный ответ на вопрос «что чистить» и «что чинить в генераторе».

Точечный поиск: доминирующие расширения/имена

Иногда полезно понять, какие типы файлов плодятся. Пример (на миллионах файлов может быть тяжёлым):

find /var/log/app -xdev -type f -printf '%f
' 2>/dev/null | sed 's/.*\.//' | sort | uniq -c | sort -n | tail

Если видите гигантское количество однотипных tmp/cache/log с уникальными именами, значит приложение создаёт мусор и его нужно ограничивать политиками retention или исправлением логики записи.

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

Виртуальный хостинг FastFox
Виртуальный хостинг для сайтов
Универсальное решение для создания и размещения сайтов любой сложности в Интернете от 95₽ / мес

Как освободить inode безопасно: тактика «сначала стабилизируем»

Когда inode на нуле, задача — быстро вернуть системе возможность создавать файлы, не сломав критичные сервисы. После стабилизации уже разбирайтесь с первопричиной и профилактикой.

1) Удаляйте массово и осознанно

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

  • старые файлы в /tmp и /var/tmp;
  • кэши пакетных менеджеров;
  • рабочие директории CI/CD (особенно при неудачных сборках);
  • дублирующиеся/лишние логи (учитывайте требования хранения и аудит).

2) Если виноват journald или логирование

Когда inode кончились, ошибки логирования часто начинают множиться и усугублять ситуацию. Для journald имеет смысл проверить использование диска и при необходимости сделать «вакуум» (это больше про объём, но иногда помогает снять давление и вернуть управляемость):

journalctl --disk-usage
journalctl --vacuum-time=7d
journalctl --vacuum-size=500M

Если же проблема в миллионах отдельных файлов логов приложения, лечится это не journald, а схемой логирования и корректной ротацией.

3) Если виноват Docker: чистим неиспользуемые объекты

Перед очисткой оцените, что именно съедает место и (косвенно) inode:

docker system df

Дальше начинайте с наиболее безопасных вариантов (не удаляют работающие контейнеры):

docker container prune
docker image prune -a
docker network prune

С volumes будьте аккуратнее: они часто содержат данные. Применяйте только если уверены, что «висячие» тома действительно не нужны:

docker volume prune

И самый радикальный вариант, который обычно быстро возвращает ресурсы, но может снести много кэша и замедлить следующие деплои:

docker system prune -a

Если после очистки проблема повторяется, пересмотрите сборку образов (уменьшайте количество мелких файлов, чистите кэши в слоях) и правила хранения артефактов. Про практичную настройку сетевой части Docker см. также: Docker и firewall: iptables/nftables без сюрпризов.

4) Остановите «производителя» файлов, иначе всё вернётся

Если вы удаляете мусор, а inode снова заканчиваются через минуты, значит есть активный генератор: кривой логгер, бесконечный ретрай, воркер с ошибкой, агент, который спамит файлами. В этом случае иногда правильнее временно остановить сервис, освободить inode и только потом включать после правки конфигурации/кода.

Профилактика: как сделать так, чтобы inode не кончались снова

Изолируйте «мелкофайловые» зоны

Практика, которая спасает от больших инцидентов: вынести потенциально опасные области в отдельные файловые системы/тома. Тогда даже если inode закончатся в одном месте, вся система останется управляемой.

  • /var/lib/docker на отдельный раздел под профиль контейнеров;
  • /var/log отдельно или централизованный сбор логов;
  • кэши и артефакты CI отдельно от системного раздела;
  • /tmp в tmpfs, если подходит по памяти и вашей модели угроз.

Нормальная retention-политика: логи, кэши, артефакты

  • проверьте, что logrotate реально ротирует нужные файлы и не создаёт «лес» по ошибочному шаблону;
  • убедитесь, что приложение не пишет «один файл на событие», если это не осознанный дизайн;
  • в CI/CD настройте уборку рабочих директорий и кэшей;
  • для временных файлов задайте TTL и механизм удаления.

Очистка через systemd-tmpfiles

Для системной уборки временных каталогов используйте systemd-tmpfiles: так политика очистки становится предсказуемой и воспроизводимой. Конкретные правила зависят от путей и ваших требований к хранению, поэтому сначала протестируйте на небоевом окружении и убедитесь, что не удаляете нужные данные.

Мониторинг использования inode и пороги алертов для разделов

Мониторинг: алерты не только по диску, но и по inode

Добавьте мониторинг IUse% на ключевые маунты: /, /var, /var/lib/docker, /var/log. Пороговые значения обычно выбирают так, чтобы у вас оставалось время на реакцию (например, предупреждение 70%, критично 85%, аварийно 95%). Это дешёвый контроль, который ловит проблему до падения сервисов.

Когда «лечить нечего»: inode на ext4 нельзя просто добавить

Если вы регулярно упираетесь в inode на ext4, значит файловую систему создавали с неподходящей плотностью inode под ваш профиль данных. В большинстве типовых сценариев «увеличить количество inode на месте» нельзя: нужно мигрировать данные на новый раздел/том, пересоздать ФС с другими параметрами или менять архитектуру хранения (уменьшать число файлов, упаковывать объекты в архивы, переносить часть в БД/хранилище).

Короткий чеклист: inode usage troubleshooting

  1. Подтвердить проблему: df -i.
  2. Найти маунт для конкретного пути: findmnt -T /path.
  3. Определить «каталоги-лидеры» по числу объектов (find + wc -l с -xdev).
  4. Быстро освободить inode: удалить/почистить мусор (tmp, кэши, артефакты), при необходимости остановить генератор файлов.
  5. Если Docker: оценить docker system df, применить prune по ситуации, затем исправить пайплайны/образы.
  6. Сделать профилактику: retention, systemd-tmpfiles, мониторинг inode, изоляция разделов.

Итоги

ENOSPC — это не всегда про гигабайты. Когда кончаются inode, система выглядит «свободной» по df -h, но отказывается создавать файлы. Самый рабочий порядок действий: подтвердить df -i, быстро найти каталоги с миллионами объектов, аккуратно освободить inode и закрепить профилактикой (retention, автоматическая очистка, мониторинг, грамотная разметка).

Если вы держите проекты на виртуальном хостинге или на VDS, заранее добавьте алерты по inode и вынесите «шумные» каталоги (логи, Docker data root, артефакты) на отдельные тома: так инциденты с inode будут локальными и быстрее лечиться.

Поделиться статьей

Вам будет интересно

systemd: journalctl, systemctl status и лимиты запуска StartLimit/Timeout* без боли OpenAI Статья написана AI (GPT 5)

systemd: journalctl, systemctl status и лимиты запуска StartLimit/Timeout* без боли

Если сервис в systemd уходит в restart loop, падает с failed to start или «не успевает» подняться — почти всегда дело в логах и ли ...
Systemd-boot и UKI: unified kernel images для Secure Boot-ready VDS на Debian/Ubuntu OpenAI Статья написана AI (GPT 5)

Systemd-boot и UKI: unified kernel images для Secure Boot-ready VDS на Debian/Ubuntu

Практический разбор UKI (unified kernel image) и systemd-boot для Debian/Ubuntu на VDS: проверяем UEFI и ESP, ставим загрузчик, со ...
Linux: TCP Fast Open (TFO) для Nginx через systemd sysctl — включение, проверка и отладка OpenAI Статья написана AI (GPT 5)

Linux: TCP Fast Open (TFO) для Nginx через systemd sysctl — включение, проверка и отладка

TCP Fast Open (TFO) ускоряет старт TCP-соединения за счёт данных в SYN при повторных подключениях. Показываю, как включить net.ipv ...