Короткий ответ

Сначала df -h и df -i по всем точкам монтирования, затем du -xhd1 только по тому, который заполнен. Не делайте rm -rf /var/log и не чистите /home «на глаз». Частые безопасные источники: journald, apt archives, старые ядра, Docker overlay, удалённые, но открытые файлы (lsof +L1). Если df 100%, а du не сходится — место держит процесс; рестарт того процесса освободит блоки, rm уже ничего не даст.

Хост host.example (10.0.20.10), пользователь admin.

Симптомы и как отличить

  • приложения пишут No space left on device;
  • apt-get update обрывается на unpack;
  • journalctl ругается на systemd-journal;
  • SSH ещё жив, но sudo не пишет /var/log/auth.log.

Отличия:

КартинаНе гигабайтыСтатья
df -h свободно, df -i 100%inodeЗакончились inode
Том в roдиск/контроллерRead-only ФС
Только /var/log/journalполитика journaldЛоги journald заняли диск
dpkg lock + ENOSPCоборванный aptdpkg заблокирован

Возможные причины

  1. Рост /var/log/journal без SystemMaxUse.
  2. /var/cache/apt/archives после неудачных upgrade.
  3. Несколько linux-image в /boot (отдельный раздел 1 ГБ).
  4. Docker/containerd: overlay2, containerd snapshots.
  5. Дампы coredumpctl, /var/crash, mysql binlog, backup в /tmp.
  6. Файл 50 ГБ удалили, процесс держит fd — du уже не видит, df видит.

Диагностика

df -hT
df -i
lsblk -o NAME,SIZE,FSTYPE,MOUNTPOINT
findmnt -t ext4,xfs,btrfs

На заполненном томе (пример — /):

sudo du -xhd1 / | sort -h
sudo du -xhd1 /var | sort -h
sudo du -xhd1 /var/log | sort -h
journalctl --disk-usage
sudo du -sh /var/cache/apt/archives /var/crash /var/tmp /tmp

Флаг -x не уходит на другие ФС: иначе du / суммирует NFS и врёт.

Открытые удалённые:

sudo lsof +L1 | awk 'NR==1 || $3=="0"' | head
sudo lsof +L1 | awk '$3=="0" {s+=$7} END {print s}'

Docker, если стоит:

sudo du -xhd1 /var/lib/docker 2>/dev/null | sort -h | tail
sudo docker system df

/boot:

df -h /boot
dpkg -l 'linux-image-*' | grep ^ii

Решение

Сценарий A. Journald

Точечно, с сохранением срока, который вам нужен для расследований:

sudo journalctl --vacuum-size=300M

Постоянный лимит — в статье про journald, не отключайте journal.

Сценарий B. APT и ядра

sudo apt-get clean
sudo apt-get autoremove --purge

На /boot удаляйте старые linux-image, оставив текущее и одно предыдущее:

uname -r

Сценарий C. Open-deleted

Найдите PID из lsof +L1. Рестарт этого сервиса (systemctl restart …), не reboot всего хоста, если можно избежать. После рестарта df должен упасть.

Сценарий D. Большие логи приложения

Ротация через logrotate для /var/log/nginx и т.п. Сжатие gzip старых файлов безопаснее удаления за сегодня.

Сценарий E. Нужно место прямо сейчас, виновник неизвестен

Ищите файлы >500 МБ:

sudo find / -xdev -type f -size +500M -printf '%s %p\n' 2>/dev/null | sort -n | tail -n 20

Не удаляйте /var/lib/mysql, /var/lib/postgresql, /var/lib/docker/volumes. Сначала snapshot.

Что смотреть на Ubuntu 22.04 и 24.04 отдельно

На 22.04 journal по умолчанию persistent, если существует /var/log/journal; размер часто не ограничен явно, и на корне 100 ГБ journal спокойно занимает десятки гигабайт. На 24.04 то же плюс needrestart и более болтливый unattended-upgrades в term.log. Перед vacuum journal скопируйте journalctl -b -0 -o export на другой том: иначе инцидент ENOSPC останется без улик.

Типичная ловушка гипервизора: гость видит df 40 ГБ свободно, а datastore thin pool на хосте 0 байт. Тогда dd в файл на / получает I/O error, не ENOSPC. Проверьте dmesg на I/O error параллельно с df. Если thin pool — чините хранилище, не apt-get clean.

Для LVM thin в госте:

sudo lvs -o lv_name,data_percent,metadata_percent,lv_size
sudo vgs -o vg_name,vg_free,vg_size

data_percent близко к 100 на thin LV даёт те же симптомы, что заполненный ext4. Расширение LV (lvextend -r) — только после свободного места в VG и snapshot политики.

Не удаляйте /var/lib/containerd и overlay Docker, пока docker ps -a не показал, что контейнеры расходные. На 24.04 docker system df -v показывает volumes по имени: volume с базой выглядит как «unused», если контейнер остановлен.

Отдельный раздел /boot на 1 ГБ после нескольких linux-image generic и HWE заполняется файлами initrd по 80–100 МБ. Команда dpkg -l 'linux-image-*' плюс uname -r обязательна до autoremove. Если /boot vfat EFI + отдельный ext4 /bootdf -h /boot /boot/efi оба.

Когда admin заходит по SSH и не может писать в home, а корень ещё не 100%, проверьте квоты:

sudo repquota -a
quota -u admin

Квоты на Ubuntu Server по умолчанию выключены; если включены на /home, это не «диск кончился глобально».

Как проверить, что проблема устранена

df -h /
df -i /
journalctl --disk-usage
sudo systemctl is-system-running
sudo apt-get check
touch /tmp/.space-ok && rm /tmp/.space-ok

Сервис, который падал с ENOSPC, должен писать лог. Повторите операцию, которая ломалась (пакет, backup, upload).

С admin@10.0.20.10 достаточно df -h в мониторинг: порог 80/90%, не 99%.

Если не помогло

  • df всё ещё 100%, du маленький: снова lsof +L1, snapshot LVM thin, qcow2 на гипервизоре.
  • Thin pool гипервизора заполнен — гость видит «диск полный» при пустом du. Смотрите хост, не Ubuntu.
  • Btrfs: btrfs filesystem usage — снимки subvolume.
  • Запись есть, чтение нет: не ENOSPC, а read-only.

Профилактика

  • Отдельный LV под /var и /var/log на нагруженных логами узлах.
  • SystemMaxUse для journald, logrotate приложений.
  • Алерт df 80%, отдельный алерт df -i.
  • Не складывать backup на системный диск host.example.

FAQ

Почему du меньше df?

Другие ФС без -x, reserved blocks ext4 (обычно 5% root), open-deleted, snapshot.

Можно ли уменьшать reserved blocks?

tune2fs -m 1 на больших томах допустимо, на корне 100 ГБ экономия копеечная. Не ставьте 0% на системный диск.

rm большого файла не меняет df?

Процесс держит inode. lsof на путь или +L1.

Чистить /tmp через reboot?

На Ubuntu /tmp часто tmpfs или чистится systemd-tmpfiles. Reboot — грубый способ; лучше найти потребителя.

Безопасно ли удалять /var/log/journal целиком?

Хуже, чем vacuum: теряете историю инцидента. Используйте --vacuum-size / --vacuum-time.