Что было. Корневой раздел 57 ГБ, df показывает 54 ГБ занято и 1,1 ГБ свободно. Пользователь сложил размеры каталогов вручную и получил меньше 30 ГБ. Помощники попросили вывод du -xh --max-depth=1 /, и он показал 34 ГБ в /media.
Причина. В /media/<имя> когда-то скопировали 34 ГБ данных, пока внешний диск не был подключён. Потом диск смонтировали в тот же каталог, и содержимое каталога оказалось скрыто под точкой монтирования: ни файловый менеджер, ни du с обычными путями его не показывали, а место на корневом разделе оно занимало. Автор нашёл каталог, освободил место, подтвердил.
Почему du -x это увидел. Ключ -x не переходит на другие файловые системы, поэтому du -xh --max-depth=1 / считает только то, что лежит на корневом разделе, включая содержимое каталогов под точками монтирования (при смонтированном диске du -x покажет для точки монтирования ноль, поэтому расхождение между суммой du -x и df само по себе уже указывает на скрытые данные, а увидеть их можно только отмонтировав диск или через bind-mount корня). В обсуждении вывод du совпал с df после того, как учли /media, и это подсказало направление.
Надёжный способ увидеть скрытые данные без отмонтирования:
mkdir /mnt/rootview
mount --bind / /mnt/rootview # корень как есть, без вложенных монтирований
du -sh /mnt/rootview/media/* /mnt/rootview/mnt/* /mnt/rootview/srv/* 2>/dev/null
umount /mnt/rootview
Что покажет ненулевой размер, то и лежит под точкой монтирования.
Как это случается на серверах.
- Задача резервного копирования пишет в
/mnt/backup, когда диск не смонтирован (об этом отдельный разбор с проверкойmountpoint). - Сервис стартует раньше, чем подключается сетевой или внешний том, и создаёт данные в пустом каталоге; потом том монтируется поверх. Лечится зависимостями в systemd (
RequiresMountsFor=/srv/dataв юните сервиса) и опциейx-systemd.automount. - Контейнеры с bind-mount на несмонтированный каталог хоста.
Профилактика. Права 000 на пустые точки монтирования (запись невозможна, пока диск не смонтирован), nofail в fstab для внешних дисков, и проверка findmnt <путь> в скриптах перед записью.
Монтирование описано в документации Ubuntu.