Введение / Зачем это нужно
Свободное место на диске сервера или рабочей станции под Linux со временем заполняется временными файлами, кэшем приложений, старыми логами и отладочными дампами. Ручная очистка отнимает время и часто забывается, что приводит к заполнению корневого раздела (/) и сбоям системы.
Этот гайд покажет, как настроить безопасную автоматическую очистку диска с помощью cron или systemd-timer. Вы сможете:
- Регулярно удалять файлы в
/tmp,/var/tmp - Очищать старые логи из
/var/log(с учетом политики ротации) - Удалять устаревший кэш пакетного менеджера (
apt,dnf,pacman) - Контролировать размер домашних каталогов пользователей
Все действия безопасны и используют возраст файлов как критерий.
Требования / Подготовка
Перед настройкой убедитесь, что:
- У вас есть права
sudoили доступ кroot. - Установлены утилиты для анализа диска (рекомендуется
ncdu):# Ubuntu/Debian sudo apt update && sudo apt install ncdu # Fedora/CentOS/RHEL sudo dnf install ncdu # Arch sudo pacman -S ncdu - Вы знаете, какие каталоги на вашей системе занимают больше всего места. Выполните:
Или, еслиsudo ncdu /ncduнет:sudo du -h --max-depth=1 / 2>/dev/null | sort -hr
Шаг 1: Создание скрипта очистки
Создайте файл, например, /usr/local/bin/disk-cleanup.sh:
#!/usr/bin/env bash
# disk-cleanup.sh — автоматическая очистка диска в Linux
# Удаляет временные файлы, старые логи и кэш старше N дней.
# Безопасность: проверяет, что удаляемые пути существуют.
set -euo pipefail # Безопасный режим bash
# Конфигурация (измените под себя)
TMP_DIRS=("/tmp" "/var/tmp")
LOG_DIRS=("/var/log")
CACHE_DIRS=(
"/var/cache/apt/archives/partial"
"/var/cache/dnf"
"/var/cache/pacman/pkg"
"/root/.cache"
)
DAYS_OLD=7 # Удалять файлы старше 7 дней
MIN_FREE_PERCENT=10 # Минимальный свободный процент для запуска (необязательно)
# Функция для безопасного удаления файлов старше N дней
clean_directory() {
local dir="$1"
local days="$2"
if [[ ! -d "$dir" ]]; then
echo "⚠️ Каталог $dir не существует, пропускаем."
return 0
fi
echo "🧹 Очищаем $dir (файлы старше $days дней)..."
# Находим и удаляем файлы, но не сами каталоги
find "$dir" -type f -mtime +"$days" -print -delete 2>/dev/null || true
# Удаляем пустые каталоги (глубина 1, чтобы не затронуть структуру)
find "$dir" -mindepth 1 -depth -type d -empty -delete 2>/dev/null || true
}
# Функция для очистки кэша пакетных менеджеров
clean_package_cache() {
echo "📦 Очистка кэша пакетных менеджеров..."
# APT (Debian/Ubuntu)
if command -v apt-get &>/dev/null; then
echo " → APT: удаление устаревших .deb файлов..."
apt-get clean -y 2>/dev/null || true
fi
# DNF (Fedora/RHEL/CentOS)
if command -v dnf &>/dev/null; then
echo " → DNF: удаление устаревших пакетов..."
dnf clean all -y 2>/dev/null || true
fi
# Pacman (Arch)
if command -v pacman &>/dev/null; then
echo " → Pacman: удаление устаревших пакетов..."
pacman -Sc --noconfirm 2>/dev/null || true
fi
}
# Основная логика
echo "🚀 Начало очистки диска $(date)"
# 1. Временные файлы
for dir in "${TMP_DIRS[@]}"; do
clean_directory "$dir" "$DAYS_OLD"
done
# 2. Кэш пакетных менеджеров
clean_package_cache
# 3. Логи (только старые файлы, не трогаем текущие)
for dir in "${LOG_DIRS[@]}"; do
# Удаляем сжатые и старые логи, но оставляем последние 7 файлов
if [[ -d "$dir" ]]; then
echo "📄 Очистка логов в $dir (файлы старше $DAYS_OLD дней)..."
find "$dir" -type f -name "*.log.*" -mtime +"$DAYS_OLD" -print -delete 2>/dev/null || true
find "$dir" -type f -name "*.gz" -mtime +"$DAYS_OLD" -print -delete 2>/dev/null || true
fi
done
# 4. Дополнительно: кэш пользователей (осторожно!)
# Раскомментируйте, если нужно:
# clean_directory "/home/*/.cache" "$DAYS_OLD"
echo "✅ Очистка завершена $(date)"
echo "📊 Текущее использование диска:"
df -h / 2>/dev/null || true
Сделайте скрипт исполняемым:
sudo chmod +x /usr/local/bin/disk-cleanup.sh
Комментарии к скрипту:
set -euo pipefail— безопасный режим: скрипт прервётся при ошибках.DAYS_OLD=7— изменяйте под политику (например, 3 дня для/tmp, 30 для логов).- Мы не удаляем каталоги, только файлы и пустые подкаталоги.
apt-get cleanудаляет локальный кэш.deb, но не конфигурации.- Для кэша браузеров (
~/.cache/mozilla,~/.cache/google-chrome) добавьте путь вCACHE_DIRS, но тестируйте осторожно.
Шаг 2: Настройка автоматического запуска через cron
Простой и универсальный способ.
- Откройте crontab для root:
sudo crontab -e - Добавьте строку для ежедневного запуска в 2:00 ночи:
0 2 * * * /usr/local/bin/disk-cleanup.sh >> /var/log/disk-cleanup.log 2>&1
Пояснение:0 2 * * *— каждый день в 02:00.>> /var/log/disk-cleanup.log 2>&1— весь вывод (stdout и stderr) пишется в лог.- Лог можно ротировать через
logrotate(см. Шаг 4).
- Сохраните и выйдите. Cron автоматически применит расписание.
Альтернатива: systemd-timer (рекомендуется для современных систем)
Если вы используете systemd (Ubuntu 22.04+, Fedora, CentOS 8+), это гибче и надёжнее.
- Создайте service-файл:
sudo tee /etc/systemd/system/disk-cleanup.service > /dev/null <<'EOF' [Unit] Description=Disk Cleanup Service Wants=network-online.target After=network-online.target [Service] Type=oneshot ExecStart=/usr/local/bin/disk-cleanup.sh # Запуск от root, но можно от другого пользователя через User= # User=someuser # Group=somegroup EOF - Создайте timer-файл:
sudo tee /etc/systemd/system/disk-cleanup.timer > /dev/null <<'EOF' [Unit] Description=Run disk cleanup daily Requires=disk-cleanup.service [Timer] OnCalendar=daily Persistent=true # RandomDelaySec=1h # Раскомментируйте для распределения нагрузки # Убедитесь, что время не пересекается с другими задачами [Install] WantedBy=timers.target EOF - Включите и запустите:
sudo systemctl daemon-reload sudo systemctl enable --now disk-cleanup.timer - Проверьте статус:
sudo systemctl status disk-cleanup.timer sudo systemctl list-timers | grep disk-cleanup
Преимущества systemd-timer:
- Логи автоматически попадают в
journalctl:sudo journalctl -u disk-cleanup.service. - Таймер не запустится, если система была выключена в назначенное время (
Persistent=true). - Можно настроить
RandomDelaySecдля распределения нагрузки.
Шаг 3: Настройка исключений и тонкая настройка
Добавление исключений (whitelist)
Если в очищаемых каталогах есть важные файлы, создайте список исключений:
# В начале скрипта (после set) добавьте:
EXCLUDE_PATTERNS=(
"/tmp/important-file"
"/var/log/secure" # Не удаляем логи аутентификации!
"/var/log/auth.log"
)
# Затем в функции clean_directory после find добавьте:
# Пример для /tmp:
find "$dir" -type f -mtime +"$days" ! -path "${EXCLUDE_PATTERNS[@]/#/}" -print -delete
⚠️ Важно: Никогда не добавляйте в исключения каталоги вроде
/var/logцеликом — это остановит ротацию логов. Исключайте только конкретные файлы.
Настройка под конкретные дистрибутивы
Для Ubuntu/Debian (дополнительно очищаем кэш Snap):
# Добавьте в скрипт после clean_package_cache:
if [[ -d "/var/lib/snapd/cache" ]]; then
find "/var/lib/snapd/cache" -type f -mtime +30 -delete
fi
Для серверов с маленьким /tmp в RAM (tmpfs):
# Обычно /tmp очищается при перезагрузке. Но если нужно:
clean_directory "/tmp" 1 # Только файлы старше 1 дня
Шаг 4: Проверка результата и мониторинг
Тестовый запуск
# Запустите скрипт вручную:
sudo /usr/local/bin/disk-cleanup.sh
# Или для systemd:
sudo systemctl start disk-cleanup.service
sudo systemctl status disk-cleanup.service
Проверьте, что удалено
# Посмотрите, сколько освободилось:
df -h /
# Или по каталогам:
sudo du -sh /tmp /var/log 2>/dev/null
Мониторинг через логи
- Cron:
sudo tail -f /var/log/disk-cleanup.log - Systemd:
sudo journalctl -u disk-cleanup.service -f
Настройте оповещения о свободном месте (опционально)
Добавьте в скрипт проверку свободного места и оповещение:
MIN_FREE_GB=5 # Минимум 5 ГБ свободно
FREE_SPACE=$(df --output=avail / | tail -n1) # в 1K-блоках
FREE_SPACE_GB=$((FREE_SPACE / 1024 / 1024))
if [[ $FREE_SPACE_GB -lt $MIN_FREE_GB ]]; then
echo "⚠️ Мало свободного места: ${FREE_SPACE_GB}GB" | \
mail -s "Критично: мало места на $(hostname)" admin@example.com
fi
Шаг 5: Ротация логов скрипта (если используете cron)
Создайте конфиг для logrotate:
sudo tee /etc/logrotate.d/disk-cleanup > /dev/null <<'EOF'
/var/log/disk-cleanup.log {
weekly
rotate 4
compress
missingok
notifempty
create 640 root adm
}
EOF
Для systemd логи управляются через journalctl и не требуют отдельной ротации.
Проверка результата
После настройки:
- Убедитесь, что скрипт запускается автоматически:
# Для cron: sudo grep disk-cleanup /var/log/syslog | tail # Для systemd-timer: sudo systemctl list-timers | grep disk-cleanup - Проверьте, что место освобождается:
# Зафиксируйте текущее использование: df -h / > /tmp/disk-before.txt # Через день: df -h / > /tmp/disk-after.txt diff /tmp/disk-before.txt /tmp/disk-after.txt - Убедитесь, что важные файлы не удалены (особенно в
/var/logи/tmp).
Возможные проблемы
❌ "Permission denied" при удалении файлов
Причина: Скрипт запущен не от root, а некоторые каталоги (/var/log, /tmp) требуют повышенных прав.
Решение: Запускайте скрипт через sudo (cron от root, systemd service без User=).
❌ Удаляются нужные файлы (например, активные сессии в /tmp)
Причина: Слишком маленький DAYS_OLD или нет исключений.
Решение:
- Увеличьте
DAYS_OLDдо 7-10 для/tmp. - Добавьте исключения через
! -pathвfind. - Протестируйте с
findбез-delete, чтобы увидеть список.
❌ Systemd-timer не запускается
Причина: Таймер не включён или конфликт времени. Решение:
sudo systemctl enable disk-cleanup.timer
sudo systemctl list-timers | grep disk-cleanup # Проверьте время следующего запуска
❌ Слишком агрессивная очистка кэша пакетов
Причина: apt-get clean удаляет все .deb файлы, включая те, что могут понадобиться для отката.
Решение: Используйте apt-get autoclean вместо clean — удаляет только устаревшие (без пакетов, которые ещё можно установить).
Измените строку в скрипте:
apt-get autoclean -y 2>/dev/null || true
❌ Ошибки при очистке кэша браузеров
Причина: Браузеры могут блокировать файлы или использовать сложные структуры.
Решение: Не очищайте кэш браузеров автоматически. Доверьте это встроенным функциям (например, "Очистить историю" в Firefox). Если очень нужно — удаляйте только файлы старше 30 дней и только в ~/.cache/mozilla/firefox/*.default/cache2/.
❌ Нет места после очистки
Причина: Проблема не во временных файлах, а в больших данных (логи приложений, базы данных, медиафайлы).
Решение: Используйте ncdu для поиска "тяжелых" каталогов. Возможно, потребуется:
- Архивация старых данных.
- Настройка ротации логов для конкретных приложений (например, MySQL, Docker).
- Увеличение диска.
❌ Cron не отправляет почту с ошибками
Причина: По умолчанию cron отправляет почту на local user, но MTA не настроен. Решение:
- Настройте
ssmtp/msmtpдля отправки. - Или перенаправляйте ошибки в лог (как в примере) и мониторьте его.
- Или используйте
systemd— логи вjournalctl.
Дополнительные возможности
Очистка Docker-объектов (если Docker установлен)
Добавьте в скрипт (перед clean_package_cache):
if command -v docker &>/dev/null; then
echo "🐳 Очистка Docker..."
# Удаляем остановленные контейнеры, висячие образы, сети, тома
docker system prune -af --volumes 2>/dev/null || true
fi
💡 Совет: Для production-серверов используйте
docker system pruneс осторожностью. Лучше настроить--filter "until=24h"или удалять только dangling образы (docker image prune -f).
Очистка старых ядер (Ubuntu/Debian)
Количество установленных ядер может занимать гигабайты. Добавьте:
# Удаляет старые ядра, оставляя последние 2
if command -v apt-get &>/dev/null; then
echo "🔄 Очистка старых ядер..."
# Вариант 1: автоматически (осторожно!)
# apt-get autoremove --purge -y
# Вариант 2: ручной список (рекомендуется)
# dpkg -l 'linux-image-*' | grep '^ii' | awk '{print $2}' | \
# grep -v "$(uname -r)" | grep -v "$(uname -r | sed 's/-generic//')" | \
# xargs sudo apt-get purge -y 2>/dev/null || true
fi
⚠️ Важно: Не удаляйте текущее ядро (
uname -r). Лучше оставляйте 2 последних.
Интеграция с tmpreaper или tmpwatch
Некоторые дистрибутивы (RHEL, CentOS) используют tmpwatch для очистки /tmp. Вместо своего скрипта можно настроить его:
# Для CentOS/RHEL:
sudo yum install tmpwatch
sudo tee /etc/cron.daily/tmpwatch <<'EOF'
#!/bin/sh
/usr/sbin/tmpwatch 24 /tmp
/usr/sbin/tmpwatch 48 /var/tmp
EOF
sudo chmod +x /etc/cron.daily/tmpwatch
Но наш скрипт более универсален и включает кэш пакетов.
Заключение (не добавляем как отдельную секцию)
Автоматизация очистки диска — обязательная практика для поддержания здоровья Linux-системы. Вы настроили:
- Гибкий скрипт с настройками под ваш дистрибутив.
- Запуск через cron или systemd-timer.
- Логирование и мониторинг.
Следующие шаги:
- Тестируйте скрипт в
--dry-runрежиме (добавьтеechoвместо-delete). - Настройте алерты на свободное место (например, через
monitилиzabbix). - Для серверов рассмотрите централизованный сбор логов (ELK, Graylog) — это сократит нагрузку на локальные диски.
Если место всё равно заканчивается, ищите "тяжёлые" каталоги через ncdu — возможно, проблема в данных, а не во временных файлах.