No space left on device: что значит и как освободить место в Linux

опубликовано
читать
≈ 5 мин
автор
среда и версия
Debian 12: coreutils 9.1, lsof 4.95, Python 3.11; маленькие диски tmpfs на 2 МБ и на 64 inode
содержание пройти тест Linux

No space left on device переводится как «на устройстве не осталось места». Программа попыталась записать данные, а файловая система отказала: кончилось место на диске или запас inode — записей о файлах. У этой ошибки код ENOSPC, и пишут её все программы одинаково: dd, оболочка, Python, Docker, база данных.

Причин три, и проверяются они тремя командами: место кончилось на самом деле (df -h), кончились inode (df -i) или место держит удалённый, но всё ещё открытый файл (lsof +L1). Ниже — каждая на живом выводе: стенд из маленьких дисков на 2 МБ и на 64 файла в Debian 12.

Linux / 01

Три причины и чем каждую проверить

Три причины и чем каждую проверить01 кончилось место: df -h показывает 100% в столбце Use%, решение — удалить лишнее, найдя его через du -sh. 02 кончились inode: df -h показывает 0%, но df -i — 100% в столбце IUse%, решение — удалить мелкие файлы: кэш, сессии, очереди. 03 файл удалён, но открыт: после rm df -h всё ещё показывает 100%, lsof +L1 находит файл с пометкой deleted, решение — перезапустить процесс, который его держит.причиначем проверитьчто сделать01 кончилось местобайты, гигабайтыdf -hUse% 100%удалить лишнеенайти через du -sh02 кончились inodeзаписи о файлахdf -iIUse% 100%удалить мелкие файлыкэш, сессии, очереди03 удалён, но открытместо держит процессlsof +L1(deleted)перезапустить процесскоторый держит файл
Если df -h показывает свободное место, а ошибка есть, проверь inode. Если место после удаления не освободилось — ищи процесс, который держит удалённый файл.

Как выглядит ошибка

Разные программы сообщают о ней по-разному, но слова в конце одни. Запишем на пустой диск в 2 МБ файл на 5 МБ, а потом попробуем дописать строку в лог из оболочки и из Python:

dd if=/dev/zero of=/data/backup.img bs=1M count=5
echo "строка лога" >> /data/app.log
python3 -c "open('/data/app.log', 'a').write('x' * 100000)"
dd: error writing '/data/backup.img': No space left on device
3+0 records in
2+0 records out
2097152 bytes (2.1 MB, 2.0 MiB) copied, 0.000936413 s, 2.2 GB/s
bash: echo: write error: No space left on device
Traceback (most recent call last):
  File "<string>", line 1, in <module>
OSError: [Errno 28] No space left on device

dd успел записать 2 МБ — ровно столько, сколько было свободно, — и остановился. В Python та же ошибка приходит как OSError с номером 28.

Причина 1: кончилось место

Первая команда — df -h: сколько места на каждой файловой системе, в понятных единицах.

df -h /data
Filesystem      Size  Used Avail Use% Mounted on
tmpfs           2.0M  2.0M     0 100% /data

Use% 100% и Avail 0 — диск заполнен. Дальше нужно найти, что его заняло. du -sh показывает размер каждого файла и каталога, а sort -h ставит самые большие в конец:

du -sh /data/* | sort -h
0	/data/app.log
2.0M	/data/backup.img

На настоящем сервере начинают с корня и спускаются вглубь: sudo du -xh --max-depth=1 / | sort -h. Ключ -x не даёт du уходить на другие диски. Частые виновники:

  • логи в /var/log, особенно журнал systemd — его ужимают командой sudo journalctl --vacuum-size=200M;
  • кэш пакетов, который чистит sudo apt clean;
  • образы, контейнеры и кэш сборки Docker — о нём ниже;
  • забытые бэкапы и дампы баз данных.

Причина 2: кончились inode

У каждого файла есть inode — запись с его владельцем, правами и адресом данных. На ext4, самой частой файловой системе Linux, число inode задаётся при её создании. Если файлов очень много, inode кончаются раньше места, и df -h показывает свободный диск. Создадим пустые файлы на диске, где inode всего 64:

mkdir /files/cache
for i in $(seq 1 100); do touch /files/cache/item$i || break; done
df -h /files
df -i /files
touch: cannot touch '/files/cache/item57': No space left on device
Filesystem      Size  Used Avail Use% Mounted on
tmpfs            10M     0   10M   0% /files
Filesystem     Inodes IUsed IFree IUse% Mounted on
tmpfs              64    64     0  100% /files

Файлы пустые, места свободно 10 МБ, а IUse% 100% — и 57-й файл создать уже нельзя. На стенде это 64 inode, на реальных серверах так заканчиваются миллионы: кэш, файлы сессий, письма в очереди, миниатюры. Найди каталог, где файлов больше всего, — du --inodes -x / | sort -n | tail — и удали ненужные.

Причина 3: файл удалён, но открыт

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

sleep 3600 < /data/backup.img &
rm /data/backup.img && df -h /data
Filesystem      Size  Used Avail Use% Mounted on
tmpfs           2.0M  2.0M     0 100% /data

Такие файлы находит lsof +L1 — это открытые файлы, у которых не осталось ни одного имени:

lsof +L1 /data
COMMAND  PID USER   FD   TYPE DEVICE SIZE/OFF NLINK NODE NAME
sleep   3362  dev    0r   REG  0,417  2097152     0    5 /data/backup.img (deleted)

Процесс sleep с PID 3362 держит удалённый файл размером 2 МБ, а NLINK 0 значит, что имён у файла не осталось. Как только процесс завершится, место вернётся:

kill 3362
df -h /data
Filesystem      Size  Used Avail Use% Mounted on
tmpfs           2.0M     0  2.0M   0% /data

На сервере это обычно служба, которая пишет в лог, — её перезапускают через systemctl. Чтобы не попадать в эту ловушку, большой лог очищают, а не удаляют: : > /var/log/app.log обнуляет файл, и процесс продолжает писать в него же. Подробнее о процессах и сигналах — в статье про процессы.

Docker: образы и кэш сборки

Если ошибка появилась при docker build или docker pull, скорее всего, место съел сам Docker. Посмотреть, сколько занимают образы, контейнеры, тома и кэш сборки, можно командой docker system df. Удалить остановленные контейнеры, неиспользуемые сети, образы без тегов и кэш сборки — docker system prune. С ключом -a удаляются и все образы, которыми не пользуется ни один контейнер. Тома команда не трогает без --volumes, и это правильно: в томах лежат данные баз.

Ошибки, на которых спотыкаются

Ищут место не на том диске. Ошибка относится к файловой системе, куда шла запись, а не к корню. df -h /путь/к/папке показывает именно её.

Удаляют лог, который пишется прямо сейчас. Место не вернётся, пока служба не перезапустится. Лог очищают через : > файл или настраивают ротацию.

Чистят Docker с --volumes на сервере с базой. Тома с данными уйдут вместе с кэшем. Сначала посмотри docker system df -v, потом удаляй точечно.

Смотрят только df -h. Свободные гигабайты при 100% inode выглядят как загадка. Если места много, а ошибка есть, проверь df -i.

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

Как перевести No space left on device

«На устройстве не осталось места». Устройство здесь — файловая система, куда программа пыталась записать данные.

Что значит Errno 28 в Python

Это номер ошибки ENOSPC в Linux. OSError: [Errno 28] No space left on device значит то же самое: диск или inode кончились. Проверяй их командами df -h и df -i, как в разделах выше.

Почему место не освободилось после удаления файла

Файл открыт процессом. lsof +L1 покажет, каким именно, а перезапуск процесса вернёт место.

Источники

Выжимки статей в Telegram: одна ловушка, код с выводом и ссылка на полный разбор. t.me/koddo_ru