Диск и inode: df, du и поиск причины ENOSPC
Автор: Казачкин Даниил Михайлович · Обновлено
Ошибка No space left on device (ENOSPC) возникает не только при исчерпании блоков: файловая система может закончить inode, а процесс — удерживать уже удалённый большой файл и не…
Ошибка No space left on device (ENOSPC) возникает не только при исчерпании блоков: файловая система может закончить inode, а процесс — удерживать уже удалённый большой файл и не освобождать blocks. Квота пользователя вызывает отдельную ошибку EDQUOT, но входит в то же дерево диагностики неуспешной записи. df и du измеряют разные уровни и потому не обязаны совпадать.
df показывает файловую систему
Передавайте df путь, который реально должен принять запись: так команда выберет соответствующий mount, а не случайную строку из общего списка.
df -h /var/tmp
df -i /var/tmp
findmnt -T /var/tmp 2>/dev/null || truedf -h показывает занятые blocks, df -i — inode. Сто процентов inode при наличии гигабайтов свободного места типично для огромного числа маленьких файлов.
du объясняет видимое дерево
sudo du -xhd1 /var 2>/tmp/du-errors.log | sort -h
du -sh /var/log/* 2>/dev/null | sort -h | tail-x не переходит на другие filesystems, -d1 ограничивает глубину. Ошибки доступа нельзя бездумно скрывать: неполный обход занижает сумму. Сначала анализируйте без удаления и учитывайте mount boundaries.
Apparent size и реально выделенные blocks
Sparse file имеет большое логическое расстояние между байтами, но занимает мало blocks.
tmp_file=$(mktemp)
truncate -s 100M "$tmp_file"
ls -lh "$tmp_file"
du -h "$tmp_file"
du -h --apparent-size "$tmp_file"
rm -- "$tmp_file"Поэтому размер ls и usage du могут различаться без ошибки.
Удалённый файл всё ещё занимает место
unlink убирает имя, но blocks освобождаются после закрытия последнего file descriptor. lsof +L1 помогает найти deleted open files. Правильное действие — корректно перезапустить или заставить owner переоткрыть log; обнуление через чужой fd и kill -9 несут риск потери данных.
Ошибка и диагностика
Опасный ответ на отказ записи — удалить самый большой путь по первой выдаче. Сначала сохраните точное сообщение или errno: для ENOSPC определите mount через df/findmnt, проверьте blocks и inode, сравните du с df и найдите deleted-open files; для EDQUOT отдельно проверьте пользовательскую или групповую quota. Удаляйте только известные regenerable данные по retention policy. Логи должны ротироваться согласованно с процессом.
Практика
Создайте обычный и sparse file одинакового apparent size, сравните ls, du и du --apparent-size. На выбранном безопасном каталоге получите df -h/df -i и список первого уровня без удаления. Составьте дерево решений для случаев: blocks 100%, inode 100%, df намного больше du.
Что важно запомнить
- df измеряет filesystem allocation, du — достижимые файлы выбранного дерева.
ENOSPCуказывает на нехватку места или inode на device; исчерпанная quota возвращается отдельно какEDQUOT.- Освобождение места должно следовать ownership и retention, а не случайному rm.
Частые вопросы
Почему df не уменьшился после rm большого лога?
Процесс мог оставить файл открытым. Найдите deleted descriptor и корректно переоткройте log или перезапустите owner.
Что такое inode простыми словами?
Это структура metadata объекта filesystem. Каждый файл обычно требует inode независимо от малого размера содержимого.
Почему root видит другое свободное место?
Filesystem может резервировать blocks, а quota и permissions различаются. Диагностируйте под identity проблемного процесса.
Связанные исследования
- Почему контейнер долго запускается: ленивая загрузка от Slacker до CoFS — Как отделить скачивание, распаковку и готовность приложения; исследования Slacker и CoFS, модель задержек чтения и проверка пределов lazy pulling.
- Docker и KVM: как читать сравнение производительности и поставить своё — Историческое исследование IBM о Docker и KVM и современная методика собственного сравнения: эквивалентные условия, парные замеры, задержка и пропускная способность.