65 лет полету человека в космос! Хостинг и домены со скидкой
до 22.04.2026 Подробнее
Выберите продукт

Linux disk full: почему df и du расходятся и как найти удалённые, но занятые файлы через lsof

Когда Linux сообщает no space left on device, а du не показывает больших каталогов, часто виноваты удалённые, но открытые файлы. Разбираем du vs df, поиск через lsof и /proc, безопасное освобождение места и профилактику.
Linux disk full: почему df и du расходятся и как найти удалённые, но занятые файлы через lsof

Когда в Linux внезапно начинается «linux disk full» и всё падает с no space left on device, первая реакция — посмотреть df -h и удалить пару больших файлов. Но иногда удаление «не помогает»: df по-прежнему показывает 100%, а du в каталогах не находит ничего критичного.

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

Симптомы: когда это точно не «просто много файлов»

Типичные признаки ситуации с удалёнными, но занятыми файлами:

  • df -h показывает 95–100% занято, запись на диск ломается.
  • du -sh / или du по отдельным каталогам не объясняет, где «съедены» гигабайты.
  • Вы удаляете логи/дампы, а свободное место по df почти не меняется.
  • Часто это всплывает после неудачной ротации логов (ручной rm активного файла, некорректные postrotate-хуки, иногда — copytruncate), либо при зависшем процессе, который продолжает писать в уже удалённый файл.

Почему df и du расходятся (du vs df простыми словами)

df смотрит на файловую систему «сверху»: сколько блоков на разделе занято (включая то, что уже не видно в каталогах). du считает «снизу»: суммирует размеры файлов, которые он может обойти по дереву директорий. Если файл удалили, он исчез из каталогов — du его уже не увидит. Но пока хотя бы один процесс держит файл открытым, блоки остаются занятыми — и это отражается в df.

Место от удалённого файла в Linux освобождается только когда файл не имеет ссылок в каталогах и его никто не держит открытым.

Быстрая проверка: вы точно смотрите на один и тот же раздел?

Частая ошибка — сравнивать разные файловые системы (bind-mount, отдельные разделы, контейнеры). Сначала определите переполненный раздел:

df -hT

Затем посмотрите «видимую» занятость по каталогам, ограничившись текущей ФС ключом -x:

du -xhd1 / | sort -h

Сравнение вывода df и du при расхождении занятого места на Linux

Шаг 1. Найти открытые удалённые файлы (lsof +L1)

Самый прямой способ — lsof. Он показывает, какие процессы держат открытые файлы, включая удалённые (обычно отмечены как (deleted)).

lsof +L1

Опция +L1 выводит файлы с количеством ссылок меньше 1, то есть удалённые из каталогов, но всё ещё открытые процессами.

Если вывод большой, сузьте поиск до типичных «пожирателей» места:

lsof +L1 -nP | grep -E '/var/log|/tmp|/var/tmp'

Как быстро найти самых «толстых» виновников

У lsof обычно есть размер/смещение в колонке SIZE/OFF, но сортировать удобнее внешними инструментами. Практичный вариант для первичной диагностики:

lsof +L1 -nP | awk '{print $7, $2, $1, $9}' | sort -n | tail -n 30

Если формат «едет» из-за пробелов в путях, переходите от общего поиска к точечному: сначала определите PID по lsof +L1, затем смотрите только его (обычно виноват 1–3 процесса: веб-сервер, php-fpm, база, логгер, агент мониторинга).

Если lsof не установлен: поиск через /proc

На минимальных образах/контейнерах lsof может отсутствовать. Тогда помогут дескрипторы в /proc:

find /proc/*/fd -lname '* (deleted)' 2>/dev/null | head

Дальше вычислите PID из пути и посмотрите, что это за процесс:

ps -p 1234 -o pid,ppid,user,cmd --forest
FastFox VDS
Облачный VDS-сервер в России
Аренда виртуальных серверов с моментальным развертыванием инфраструктуры от 195₽ / мес

Шаг 2. Освободить место безопасно: что делать с процессом-виновником

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

Вариант A (предпочтительный): корректно перезапустить сервис

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

systemctl restart nginx
systemctl restart php-fpm
systemctl restart postgresql

Перезапускайте точечно по данным lsof +L1, а не «всё подряд».

Вариант B: попросить процесс переоткрыть логи (без полного рестарта)

Многие демоны умеют переоткрывать лог-файлы по сигналу SIGHUP. Пример для PID:

kill -HUP 1234

Это работает только если конкретное приложение действительно обрабатывает SIGHUP как reopen logs. Для сервисов под systemd часто удобнее отправлять сигнал через systemd, но команды и поведение зависят от юнита и демона.

Вариант C (аварийный): обнулить открытый удалённый файл через /proc

Если перезапуск нельзя (например, идёт долгий экспорт), а вы уверены, что это именно лог/временный файл, можно освободить блоки, обнулив содержимое через FD.

  1. Найдите PID и номер FD, который указывает на (deleted).
  2. Запишите пустоту в дескриптор.
ls -l /proc/1234/fd | grep deleted
: > /proc/1234/fd/55

Используйте обнуление через /proc только для логов и временных файлов. Для данных (БД, индексы, очереди) это может привести к повреждению или неконсистентности.

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

Шаг 3. Проверьте inode’ы: «место кончилось», хотя гигабайты есть

Сообщение no space left on device может появляться, даже если по гигабайтам место ещё есть. Причина — закончились inode’ы (слишком много мелких файлов).

df -ih

Если IUse% близок к 100%, найдите каталоги с лавиной мелких файлов (кеши, сессии, временные директории, spool):

find /var -xdev -type f | wc -l
find /var -xdev -type f -printf '%h
' | sort | uniq -c | sort -n | tail -n 30

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

Поиск удалённых, но открытых файлов через /proc и файловые дескрипторы

Шаг 4. Быстрый поиск «куда ушло место», если deleted files ни при чём

Если lsof +L1 пусто или там мелочь, значит диск реально занят существующими данными. Тогда действуйте системно.

Топ по каталогам

du -xhd1 / | sort -h
du -xhd1 /var | sort -h
du -xhd1 /home | sort -h

Топ по файлам

find / -xdev -type f -printf '%s %p
' 2>/dev/null | sort -n | tail -n 30

Проверить журнал systemd и подчистить по политике

journalctl --disk-usage

Аккуратно задайте удержание, не «в ноль», если логи важны для расследований:

journalctl --vacuum-time=14d

Если это Docker/контейнеры

Частый источник внезапного заполнения — слои образов и логи контейнеров.

docker system df
docker ps --size

Про контейнерную изоляцию и варианты усиления безопасности окружения можно почитать отдельно: изоляция контейнеров: gVisor и Firecracker.

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

Профилактика: как не ловить disk full из-за логов и дескрипторов

Почти всегда root cause один из двух: неправильная ротация логов или отсутствие мониторинга порогов.

Ротация логов: не удаляйте активный файл «вручную»

Типичная паническая команда (так делать не стоит):

rm -f /var/log/nginx/access.log

Если nginx продолжит писать в старый дескриптор, вы получите удалённый, но растущий файл — и тот самый конфликт du vs df. Правильнее:

  • настроить logrotate под конкретный демон;
  • использовать postrotate-хук, который заставляет сервис переоткрыть логи;
  • избегать copytruncate там, где есть штатный reopen (иначе риски потери/дубликатов строк и лишняя нагрузка на I/O).

Мониторинг: отслеживайте не только % диска

Что имеет смысл алертить:

  • занятость разделов по df (например, >80% warning, >90% critical);
  • inode’ы по df -i;
  • рост /var/log, /var/lib/docker, /tmp;
  • наличие крупных (deleted) файлов (периодическая проверка lsof +L1 по регламенту или автоматизация в мониторинге).

Короткий план действий при no space left on device

  1. df -hT — понять, какой раздел переполнен.
  2. df -ih — исключить проблему inode’ов.
  3. du -xhd1 / — оценить «видимое» место.
  4. lsof +L1 — найти удалённые, но открытые файлы.
  5. Освободить место: перезапуск сервиса или reopen logs; аварийно — обнулить через /proc/<pid>/fd/<fd>.
  6. После стабилизации — поправить ротацию и мониторинг, чтобы проблема не повторилась.

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

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

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

Debian/Ubuntu: mount: wrong fs type, bad option, bad superblock — как быстро найти и исправить причину OpenAI Статья написана AI (GPT 5)

Debian/Ubuntu: mount: wrong fs type, bad option, bad superblock — как быстро найти и исправить причину

Ошибка mount: wrong fs type, bad option, bad superblock в Debian/Ubuntu может означать и простую опечатку в имени раздела, и пробл ...
Debian/Ubuntu: XFS metadata corruption и emergency read-only — пошаговое восстановление OpenAI Статья написана AI (GPT 5)

Debian/Ubuntu: XFS metadata corruption и emergency read-only — пошаговое восстановление

Если XFS-раздел внезапно стал доступен только для чтения, а сервер ушёл в emergency mode, главное — не спешить. Разберём безопасны ...
Debian/Ubuntu: как исправить Failed to fetch при apt update OpenAI Статья написана AI (GPT 5)

Debian/Ubuntu: как исправить Failed to fetch при apt update

Ошибка Failed to fetch при apt update в Debian и Ubuntu обычно связана не с самим APT, а с DNS, сетью, зеркалом, прокси, временем ...