← Linux: администрирование
11 мин · просто · Урок 6 из 10

Диск: df, du, mount, разделы

Куда уходит место и почему «диск полный»: df vs du, точки монтирования, inode и удалённые открытые файлы.

«На диске нет места»

Самая частая авария на сервере: кончилось место, и сервис встал. Чтобы её разобрать, нужны две команды: df (сколько занято на разделах) и du (кто именно занимает).

$ df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/vda1        40G   38G  0.5G  99% /
/dev/vdb1       100G   12G   83G  13% /var/lib/postgresql
tmpfs           2.0G     0  2.0G   0% /run

df -h показывает разделы и их заполнение в человекочитаемом виде. Колонка Use% сразу говорит, где беда: корень / занят на 99%.

df против du

Это разные инструменты, их путают.

Связка такая: df показал, что переполнен /, дальше du ищет виновника:

$ du -sh /var/* | sort -h | tail -5
1.2G   /var/cache
3.4G   /var/lib
12G    /var/log

du -sh /var/* даёт размер каждого подкаталога, sort -h сортирует по-человечески (с учётом G/M/K), tail -5 показывает топ. Виновник — /var/log на 12 гигабайт.

Точки монтирования

Раздел становится доступен, когда его примонтировали в какую-то точку дерева. В выводе df колонка Mounted on — это и есть точки монтирования. /var/lib/postgresql на отдельном диске /dev/vdb1: данные базы живут не на корневом разделе.

Это важно при разборе: место может кончиться на /, пока на /var/lib/postgresql его полно. Они физически разные диски. df -h <путь> покажет, на каком разделе лежит конкретный путь.

Дерево дисков и их разделов с точками монтирования показывает lsblk:

$ lsblk
NAME   SIZE TYPE MOUNTPOINT
vda     40G disk
└─vda1  40G part /
vdb    100G disk
└─vdb1 100G part /var/lib/postgresql

Видно физические диски (vda, vdb), их разделы (vda1) и куда каждый примонтирован. Команда mount без аргументов выводит то же плюс опции монтирования (ro, noexec и прочие).

Когда df и du расходятся

Бывает: df говорит «занято», а du той же папки показывает мало. Частая причина — удалённый, но открытый файл. Процесс держит файл открытым, кто-то его удалил (rm), но место не освободилось: ядро держит его, пока процесс не закроет дескриптор или не перезапустится.

Найти такие файлы:

sudo lsof +L1

+L1 отбирает файлы, у которых число ссылок меньше единицы, то есть ровно удалённые, но ещё открытые. Root тут нужен: без него lsof не заглянет в чужие процессы и завалит вывод строками Permission denied.

В минимальных образах и контейнерах lsof часто не установлен. Тогда те же дескрипторы видно прямо в procfs:

sudo ls -l /proc/*/fd 2>/dev/null | grep deleted

В выводе будет символическая ссылка вида /var/log/app.log (deleted), а номер процесса берётся из строки заголовка /proc/<pid>/fd: выше.

После рестарта виновного процесса место вернётся. Вторая причина расхождения: du не видит файлы под точкой монтирования, которая наложилась поверх.

Что важно запомнить

df показывает заполнение разделов («где переполнено»), du — размер каталогов («что съело»). Разбор идёт df → du.

Разделы монтируются в точки дерева; место может кончиться на одном разделе, пока на соседнем его полно. df -h <путь> скажет, какой это раздел.

Если df и du расходятся, ищи удалённые открытые файлы (sudo lsof +L1, без lsof — sudo ls -l /proc/*/fd | grep deleted); место вернётся после рестарта процесса.

В связке с бэкапами: переполненный диск часто означает, что забыли чистить старые логи или дампы.

Прошли материал до конца? Отметьте урок пройденным.