← Назад к вопросам

Почему не освобождается место после удаления логов?

2.3 Middle🔥 121 комментариев
#Linux и администрирование#Мониторинг и логирование

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Основные причины незанятого места после удаления логов

Эта распространённая проблема в DevOps-практике связана с тем, что удаление файла в Linux не всегда означает освобождение дискового пространства. Вот ключевые причины и решения:

1. Процессы, удерживающие дескрипторы файлов (наиболее частая причина)

Когда процесс открывает лог-файл для записи, ядро Linux создаёт файловый дескриптор. Если удалить файл через rm или подобную команду, он физически остаётся на диске, пока его держит хотя бы один процесс.

Диагностика:

# Поиск процессов, использующих удалённые файлы
lsof +L1
lsof | grep deleted

# Альтернативный вариант через /proc
ls -la /proc/*/fd/* 2>/dev/null | grep deleted

Пример вывода:

java       12345  appuser  1w   REG   8,2  104857600   1234  /var/log/app.log (deleted)

Здесь процесс Java с PID 12345 продолжает держать дескриптор к удалённому файлу.

Решение:

# Перезапустить процесс, удерживающий файл
systemctl restart application-service

# ИЛИ отправить сигнал для закрытия файлового дескриптора
kill -HUP 12345

# ИЛИ вручную очистить через /proc (не рекомендуется для production)
> /proc/12345/fd/1

2. Монтирование дисков в режиме overlay или с особенностями файловой системы

В контейнерных средах (Docker, Kubernetes) часто используются overlay-файловые системы, где удаление файлов может не освобождать место из-за особенностей copy-on-write.

Диагностика для Docker:

# Проверить использование диска Docker
docker system df

# Детальная информация по конкретному контейнеру
docker inspect --format='{{.GraphDriver.Data}}' <container_id>

Решение:

# Очистка Docker-системы
docker system prune -a

# Для Kubernetes (очистка остановленных контейнеров на узле)
kubeclt get pods --all-namespaces | grep Evicted | awk '{print $2}' | xargs kubectl delete pod

3. Жёсткие ссылки (hard links) и точки монтирования

Если на лог-файл созданы жёсткие ссылки, удаление одной из них не освобождает место, пока все ссылки не будут удалены.

Диагностика:

# Поиск всех жёстких ссылок для файла (перед удалением)
find / -samefile /path/to/logfile 2>/dev/null

# Проверка количества ссылок
ls -li /path/to/logfile
# Второе число в выводе - количество жёстких ссылок

4. Неправильные права доступа и SELinux/AppArmor

Системы безопасности могут блокировать освобождение места.

Диагностика:

# Проверить контекст SELinux
ls -Z /path/to/logs/

# Просмотреть аудит SELinux
ausearch -m avc --start recent

5. Квоты диска (disk quotas) и резервные блоки

Дисковые квоты могут показывать занятое место, даже если файлы удалены, до следующего пересчёта.

Решение:

# Принудительный пересчёт квот
quotacheck -avug
repquota -a

Пошаговый алгоритм диагностики

  1. Определите реальное использование диска:
# Разница между df и du - ключевой индикатор
df -h /var/log
du -sh /var/log/*
  1. Найдите "висячие" файлы:
# Комплексная проверка
for pid in $(lsof +L1 | awk '{print $2}' | uniq | tail -n +2); do
    echo "PID: $pid, Command: $(ps -p $pid -o comm=)";
done
  1. Проверьте файловые системы и точки монтирования:
mount | grep -E "(overlay|aufs|zfs)" 
cat /proc/mounts | grep deleted

Практические рекомендации по предотвращению

Использование logrotate с правильной конфигурацией:

# Пример конфигурации /etc/logrotate.d/app
/var/log/app/*.log {
    daily
    rotate 7
    compress
    delaycompress  # Важно: сжатие только старых файлов
    missingok
    notifempty
    create 0644 appuser appgroup
    postrotate
        systemctl reload app-service
    endscript
}

Альтернативный подход: обнуление файлов вместо удаления

# Безопасное очищение логов с освобождением места
truncate -s 0 /var/log/large.log
# ИЛИ
> /var/log/large.log

Мониторинг и автоматизация

Настройте алерты при достижении 80% использования диска и автоматические процедуры очистки:

# Скрипт для автоматической очистки
#!/bin/bash
THRESHOLD=80
USAGE=$(df /var/log | awk 'NR==2 {print $5}' | sed 's/%//')

if [ $USAGE -gt $THRESHOLD ]; then
    echo "Disk usage exceeded $THRESHOLD%. Cleaning logs..."
    find /var/log -name "*.log" -type f -mtime +7 -delete
    # Перезапуск процессов, держащих дескрипторы
    systemctl restart relevant-services
fi

Ключевой принцип: всегда перезапускайте или переконфигурируйте процессы после ротации/удаления логов, чтобы файловые дескрипторы были корректно закрыты и место освободилось.