Linux

Автоматизация очистки диска в Linux: настройка cron и systemd

В этом гайде вы научитесь настраивать автоматическую очистку диска в Linux с помощью cron и systemd-timer. Мы рассмотрим безопасные методы удаления временных файлов, кэша браузеров и старых логов, чтобы поддерживать систему в тонусе без ручного вмешательства.

Обновлено 16 февраля 2026 г.
15-30 мин
Средняя
FixPedia Team
Применимо к:Ubuntu 22.04+Debian 11+CentOS 8+Fedora 36+Arch Linux

Введение / Зачем это нужно

Свободное место на диске сервера или рабочей станции под Linux со временем заполняется временными файлами, кэшем приложений, старыми логами и отладочными дампами. Ручная очистка отнимает время и часто забывается, что приводит к заполнению корневого раздела (/) и сбоям системы.

Этот гайд покажет, как настроить безопасную автоматическую очистку диска с помощью cron или systemd-timer. Вы сможете:

  • Регулярно удалять файлы в /tmp, /var/tmp
  • Очищать старые логи из /var/log (с учетом политики ротации)
  • Удалять устаревший кэш пакетного менеджера (apt, dnf, pacman)
  • Контролировать размер домашних каталогов пользователей

Все действия безопасны и используют возраст файлов как критерий.

Требования / Подготовка

Перед настройкой убедитесь, что:

  1. У вас есть права sudo или доступ к root.
  2. Установлены утилиты для анализа диска (рекомендуется ncdu):
    # Ubuntu/Debian
    sudo apt update && sudo apt install ncdu
    
    # Fedora/CentOS/RHEL
    sudo dnf install ncdu
    
    # Arch
    sudo pacman -S ncdu
    
  3. Вы знаете, какие каталоги на вашей системе занимают больше всего места. Выполните:
    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

Простой и универсальный способ.

  1. Откройте crontab для root:
    sudo crontab -e
    
  2. Добавьте строку для ежедневного запуска в 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).
  3. Сохраните и выйдите. Cron автоматически применит расписание.

Альтернатива: systemd-timer (рекомендуется для современных систем)

Если вы используете systemd (Ubuntu 22.04+, Fedora, CentOS 8+), это гибче и надёжнее.

  1. Создайте 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
    
  2. Создайте 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
    
  3. Включите и запустите:
    sudo systemctl daemon-reload
    sudo systemctl enable --now disk-cleanup.timer
    
  4. Проверьте статус:
    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 и не требуют отдельной ротации.

Проверка результата

После настройки:

  1. Убедитесь, что скрипт запускается автоматически:
    # Для cron:
    sudo grep disk-cleanup /var/log/syslog | tail
    
    # Для systemd-timer:
    sudo systemctl list-timers | grep disk-cleanup
    
  2. Проверьте, что место освобождается:
    # Зафиксируйте текущее использование:
    df -h / > /tmp/disk-before.txt
    
    # Через день:
    df -h / > /tmp/disk-after.txt
    diff /tmp/disk-before.txt /tmp/disk-after.txt
    
  3. Убедитесь, что важные файлы не удалены (особенно в /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.
  • Логирование и мониторинг.

Следующие шаги:

  1. Тестируйте скрипт в --dry-run режиме (добавьте echo вместо -delete).
  2. Настройте алерты на свободное место (например, через monit или zabbix).
  3. Для серверов рассмотрите централизованный сбор логов (ELK, Graylog) — это сократит нагрузку на локальные диски.

Если место всё равно заканчивается, ищите "тяжёлые" каталоги через ncdu — возможно, проблема в данных, а не во временных файлах.

Часто задаваемые вопросы

Безопасно ли автоматически удалять файлы в /tmp?
Как проверить, что скрипт очистки работает корректно?
Можно ли очищать кэш браузеров автоматически?
Что делать, если система удалила важные файлы?

Полезное

Анализ занятого пространства
Создание скрипта очистки
Настройка автоматического запуска
Тестирование и мониторинг