«Диск забит на 100%» — одна из самых частых причин отказа сервисов: перестают работать базы, логи и почта. Разберём, как быстро найти, что именно съело место, чем df отличается от du и как почистить диск без потери данных.
df: общая картина
df показывает состояние смонтированных файловых систем: общий объём, занято, свободно и процент заполнения. Начинать всегда стоит с него.
# человекочитаемый вывод
df -h
# без виртуальных файловых систем
df -h -x tmpfs -x devtmpfs
# точка монтирования, которую проверяем
df -h /var
# inode: бывает, что места много, а inode кончились
df -i
Второй случай неочевиден: масса мелких файлов исчерпывает inode раньше места. Признак — df -h показывает запас, а запись невозможна.
du: что именно занимает место
du считает занятое место в каталогах. Запускайте по корневым директориям и идите вглубь, а не сканируйте весь диск сразу.
# топ каталогов верхнего уровня
sudo du -xh --max-depth=1 / 2>/dev/null | sort -h | tail -15
# углубляемся
sudo du -xh --max-depth=1 /var 2>/dev/null | sort -h | tail -10
sudo du -xh --max-depth=1 /var/log 2>/dev/null | sort -h | tail -10
# самые большие файлы
sudo find / -xdev -type f -size +500M -exec ls -lh {} \; 2>/dev/null | head -20
Флаг -x не даёт уйти на другие разделы: иначе отчёт смешает несколько файловых систем.
Типичные виновники
- Логи без ротации:
/var/logрастёт годами. - Неочищенный кэш пакетов:
/var/cache/apt. - Огромные снапшоты или дампы баз данных.
- Контейнеры и образы:
/var/lib/docker. - Повисшие файлы удалённых процессов: они держат место, пока не закрыт дескриптор.
- Временные файлы в
/tmpи/var/tmp.
# диагностика по каждому подозреваемому
sudo du -sh /var/log /var/cache/apt /var/lib/docker /var/lib/containers 2>/dev/null
# освобождённые, но занятые файлы
sudo lsof +L1 2>/dev/null | head -20
# размер дампов
ls -lh /var/backups/*.sql* 2>/dev/null | head
Безопасная очистка
Чистите по одному каталогу и проверяйте результат. Никогда не удаляйте файлы, не понимая, кому они принадлежат.
# кэш пакетов
sudo apt clean
# старые логи (оставить 7 дней)
sudo journalctl --vacuum-time=7d
sudo find /var/log -name "*.gz" -mtime +30 -delete
# кэш контейнеров
docker system df 2>/dev/null
docker system prune -f 2>/dev/null
# после очистки
df -h /
Команды с rm -rf набирайте только после проверки пути через ls. Опечатка в подобной команде стоит данных.
Удалённые файлы, которые держат диск
Если процесс пишет в уже удалённый файл, место не освобождается до перезапуска программы. Находится это по выводу lsof.
# найти удалённые файлы с открытыми дескрипторами
sudo lsof +L1 | awk '$7 < 0 {print $1, $2, $9}' | head -20
# перезапустить конкретную службу
sudo systemctl restart nginx
# проверить
df -h /var
Профилактика
Настройте ротацию логов, квоты и мониторинг заполнения. Проще получить оповещение на 80%, чем лечить отказ на 100%.
# ротация через logrotate
cat /etc/logrotate.d/nginx 2>/dev/null
# проверить применение конфига
sudo logrotate -d /etc/logrotate.conf | tail -20
# мониторинг места: простой cron
# */30 * * * * df -h / | grep -qE '9[0-9]%' && echo "диск почти полон" | mail -s alert admin@example.com
Для баз данных планируйте ротацию дампов и храните несколько последних версий, а не все подряд.
Когда места мало, а файлов не видно
Причины: занятые inode, неправа на чтение (при сканировании без root часть каталогов пропускается), смонтированный в подкаталог раздел.
# inode
df -i
# права: запускайте du от root
sudo du -xh --max-depth=1 /var 2>/dev/null | sort -h | tail
# точки монтирования
findmnt -D | head -20
cat /proc/mounts | grep -vE "proc|sys|cgroup" | head
Когда раздел нужно расширить
Очистка не всегда помогает: данные растут, и правильное решение — увеличить раздел. На LVM это делается онлайн, на обычном разделе — переносом данных.
# состояние LVM
sudo pvs && sudo vgs && sudo lvs
# рост логического тома и файловой системы
sudo lvextend -L +5G /dev/mapper/vg0-root
sudo resize2fs /dev/mapper/vg0-root # ext4
# для XFS
# sudo xfs_growfs /
df -h /
Если свободного места в группе томов нет, добавьте физический том: pvcreate /dev/sdb1, затем vgextend и повторите рост.
Квоты на мелкие файлы
Хостинг с тысячами пользователей упирается не в место, а в inode и рост каталогов. Квоты ограничивают каждого отдельно и убирают необходимость разбирать общий диск.
# включить квоты на разделе (fstab: usrquota,grpquota)
sudo quotacheck -cum /
sudo quotaon /
# лимит для пользователя
sudo setquota -u deploy 5G 6G 200000 210000 /
# проверить
sudo repquota -us | head -15
Периодически смотрите отчёт по квотам: он сразу показывает, кто из пользователей приближается к лимиту.
Автоматические отчёты о заполнении
Вместо ручной проверки раз в месяц настройте короткий отчёт по ключевым разделам. Он приходит по почте или в мессенджер и показывает динамику: диск заполняется постепенно, и по тренду видно, когда он закончится.
#!/bin/bash
# /usr/local/bin/disk-report.sh
for m in / /var /home; do
pct=$(df -h "$m" | awk 'NR==2 {print $5}')
echo "$m -> $pct"
done | grep -E '[89][0-9]%|100%' || true
# cron: отчёт раз в день
# 0 9 * * * /usr/local/bin/disk-report.sh | head -5
Дополните отчёт местом под снапшоты и дампами: они часто растут быстрее остальных данных и незаметно заполняют раздел.
Итог
Порядок простой: df -h — где переполнено, df -i — не кончились ли inode, du вглубь — кто виноват, затем точечная очистка. Настройте ротацию логов и оповещения о заполнении: так вы узнаете о проблеме до отказа сервисов.