Webrium
Подписаться

Место на диске кончилось, а удалять нечего

Как быстро найти и устранить причину нехватки места на диске без лишних удалений и перезагрузок

Три датчика дискового пространства: блоки в норме, записи о файлах зашкаливаютЗаписи о файлах

Место на диске кончилось: что проверять раньше удаления

Сообщение об ошибке No space left on device не всегда означает, что кончились блоки данных. Прежде чем искать, что бы удалить, сделайте сразу две проверки: блоки и записи о файлах. На типовом сервере отдельными файловыми системами живут корень, раздел переменных данных, каталог контейнерного движка, загрузочный раздел и временный каталог в памяти. Чистить обычно начинают не с того раздела — путь к переполнению указан в сообщении об ошибке.

df -h <путь_из_сообщения>   # блоки
df -i <путь_из_сообщения>   # записи о файлах

Блоки проверяют первыми, но записи о файлах кончаются по своим причинам и лечатся иначе — это отдельный разговор, он ниже.

Когда кончились не блоки, а записи о файлах

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

df -i /var

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

dumpe2fs -h /dev/<раздел> | grep -i inode

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

xfs_info /var

Поднять предел доли места под записи на смонтированной файловой системе можно командой:

xfs_growfs -m <новое_значение> /var

Новый предел действует на дальнейшее выделение и уже занятое место не перераспределяет.

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

Удалённый файл, который всё ещё занимает блоки

Файловая система и обход каталогов отвечают на разные вопросы. Учёт (df) спрашивает саму файловую систему, обход (du) суммирует то, что видит в каталогах. Удалённый файл с открытым дескриптором попадает в первый ответ и не попадает во второй: имени в каталоге уже нет, блоки заняты.

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

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

Получить список удалённых файлов с открытыми дескрипторами можно командой lsof +L1. Запасной путь — каталоги дескрипторов процессов в /proc: ссылка на такой файл помечена как удалённая. На переполненном разделе установка недостающего пакета может упасть с тем же отказом записи, поэтому запасной путь надо предусмотреть заранее.

Два источника учёта: почему цифры не сходятся

Когда цифры не сходятся, начинают с порядка спуска: считают не весь диск разом, а от корня переполненной файловой системы, с ограничением на одну файловую систему и на один уровень вложенности — du -xd 1 /var | sort -n, — затем спускаются в самый тяжёлый каталог и повторяют. Один обход всего диска на полном разделе идёт долго и отнимает диск у работающих служб.

Работу сокращает не глубина, а то самое ограничение на одну файловую систему: чужие разделы обход пропускает целиком. Глубина меняет только вывод — итог по каталогу всё равно считается по всему поддереву, и повторный спуск идёт по уже пройденному, выигрывая лишь на прогретом кеше. Нагрузку на диск ограничение глубины не снимает: если обход мешает работе, снижайте ему приоритет ввода-вывода (ionice) — но сначала убедитесь, что планировщик очереди вашего диска приоритеты учитывает, учитывают их не все (cat /sys/block/<диск>/queue/scheduler).

Если после спуска нужен уже не каталог, а отдельные крупные файлы, ищите их по размеру: find /var -xdev -type f -size +<порог> -printf '%s\t%p\n' | sort -n. Порог подбирайте под свой раздел.

Обход каталогов недосчитывает систематически. Без прав на чтение каталога он молча пропускает поддерево — считайте с правами, достаточными для чтения всех каталогов. Жёсткие ссылки учитываются один раз за запуск, данные под точкой монтирования не видны. Удалённые открытые файлы не видны по определению.

Два расхождения — другой природы. Границы монтирования обход по умолчанию пересекает и тогда показывает больше, чем занято на этой файловой системе; ограничение на одну файловую систему задаётся отдельным признаком (du -x). У разреженных файлов расходятся не учёт и обход, а обход и список файлов: обход показывает занятое место, список — объявленный размер, и на образах дисков и файлах баз расхождение бывает кратным. Данные под точкой монтирования можно увидеть, не размонтируя раздел: привязочное монтирование корня нижележащей файловой системы в другое место покажет их на работающем сервере.

Сверху не сходится арифметика размера: объявленный размер раздела не равен сумме использованного и доступного. В семействе ext это доля, зарезервированная при создании файловой системы под привилегированного пользователя; своё значение смотрят командой tune2fs -l /dev/<раздел> — строка резерва блоков — и меняют ею же, ключом -m. Колонка «доступно» её уже вычитает, поэтому отказом записи «раньше, чем место кончилось» резерв ничего не объясняет. В XFS резерва под административного пользователя нет: её внутренний аварийный пул расходуется на выделение метаданных, обычному процессу места не даёт и в учёте свободного места не отражается.

Три потребителя, на которых уборка буксует

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

logrotate -d /etc/logrotate.conf

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

journalctl --disk-usage                                        # сколько занято сейчас
journalctl MESSAGE_ID=ec387f577b844b8fa948f33cad9a75e6          # какой предел действует
systemd-analyze cat-config systemd/journald.conf                # что задано явно и чем перекрыто

Уборка журнала удаляет только закрытые файлы, активный файл остаётся.

Про содержание журналов — материал Логи на сервере: почему в них «ничего нет».

Контейнерный движок скрывает главное: журналы контейнеров не входят в штатную разбивку места (docker system df). Массовая уборка (prune) их тоже не удаляет. Ищутся они обходом каталога движка по файлам журнала. У стандартного драйвера журнала предела размера файла по умолчанию нет, предел задаётся явно и смотрится командой:

docker inspect --format '{{json .HostConfig.LogConfig}}' <контейнер>

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

Что делать, когда служба уже отказала

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

Освобождение места не возвращает службу в строй автоматически. Причин три разных:

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

Чтобы не возвращаться сюда, пределы задают заранее и явно: предельный объём хранилища системного журнала, предел размера и числа файлов журнала у контейнерного движка, срок жизни кеша сборки. Оповещение по свободному месту и по скорости, с которой оно убывает, разобрано отдельно — Мониторинг с нуля: что включить в первую неделю. И держите в уме, что полный диск тише всего ломает задачи по расписанию: задача стартует, падает на первой же записи и сообщить о себе не может — её журнал уходит на тот же переполненный раздел. Об этом — Задачи по расписанию тихо перестают выполняться.

Тупик: почему удаление не помогает

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

Позиция редакции

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

С чем это связано

Метка над заголовком говорит, зачем туда идти: продолжить тему, перейти к практике или увидеть возражение.

Схема разделения: слева логи сервиса, справа зона запрета доступа, элементы пересекают границуЛоги сервисаДоступ запрещён
Практика

Логи на сервере: почему в них «ничего нет»

Как найти и проверить логи сервиса, если место на диске кончилось, а стандартные пути не работают.

Сигнал мониторинга пробивает порог сбоя до появления жалоб клиентовПорог сбояЖалобы клиентов
Углубление

Мониторинг с нуля: что включить в первую неделю

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

Четыре ключевых ресурса сервера: один из показателей зашкаливаетНехватка ресурса
Предыстория

Сервер тормозит: команды первой минуты

Как быстро диагностировать нехватку ресурсов и выявить причину тормозов сервера за минуту — без перезагрузки.

Три индикатора: два в норме, один зашкаливает без оповещенияЗадача молчит
Усиление

Задачи по расписанию тихо перестают выполняться

Если место на диске кончилось, а задачи по расписанию перестали запускаться без ошибок — здесь разбирают, почему это происходит и как сделать их работу надёжной.

Письмо по вторникам

Один разбор недели и короткий список того, что изменилось. Без дайджестов на сорок ссылок.

Начните вводить — материалы появятся здесь.

↑↓ выбрать · Enter открыть · Esc закрыть