К основному содержимому

Logrotate: автоматическая ротация логов на Linux

VDS / VPS · 15.02.2026 · 5 мин чтения
Иллюстрация к статье «Logrotate: автоматическая ротация логов на Linux»

Logrotate — стандартный инструмент Linux для управления лог-файлами. Автоматически архивирует, сжимает и удаляет старые логи по расписанию.

Как работает logrotate

  • Запускается через cron (/etc/cron.daily/logrotate)
  • Читает конфиги из /etc/logrotate.conf и /etc/logrotate.d/
  • Для каждого лога применяет правила: rotate, compress, delete

Конфиг для Nginx

sudo nano /etc/logrotate.d/nginx
/var/log/nginx/*.log {
    daily
    missingok
    rotate 14
    compress
    delaycompress
    notifempty
    create 0640 www-data adm
    sharedscripts
    postrotate
        nginx -s reopen
    endscript
}

Конфиг для вашего приложения

sudo nano /etc/logrotate.d/myapp
/var/www/myapp/logs/*.log {
    weekly
    rotate 8
    compress
    delaycompress
    missingok
    notifempty
    create 0644 www-data www-data
}

Тестирование и запуск

# Тест без реального выполнения
sudo logrotate -d /etc/logrotate.d/nginx

# Принудительный запуск
sudo logrotate -f /etc/logrotate.conf

# Проверить статус
sudo cat /var/lib/logrotate/status
ДирективаЗначение
daily/weekly/monthlyЧастота ротации
rotate NХранить N архивов
compressСжимать gzip
missingokНе ошибаться если файл отсутствует
✅ Проверяйте свободное место командой df -h. Если /var заполнен — запустите logrotate -f /etc/logrotate.conf принудительно.

Разбор типичных ошибок

Ошибка error: skipping "/var/log/nginx/access.log" because parent directory has insecure permissions появляется, если каталог с логами доступен на запись группе или всем — logrotate из соображений безопасности отказывается работать с такими путями, чтобы кто-то не подменил лог символьной ссылкой на системный файл.

error: skipping "/var/log/nginx/access.log" because parent directory has insecure permissions
(It's world writable or writable by group which is not "root")

Решение — выставить права каталога chmod 755 /var/log/nginx, а не расширять список доверенных групп в /etc/logrotate.conf: это дыра в безопасности, а не обход бага. Флаг su в правиле (su www-data www-data) иногда используют вместо исправления прав, но он лишь меняет пользователя, от имени которого logrotate выполняет ротацию, и не отменяет проверку безопасности самого каталога.

После настройки лог всё равно растёт бесконечно, хотя правило вроде бы верное. Частая причина — процесс держит старый файловый дескриптор открытым даже после ротации: без postrotate со свежим сигналом переоткрытия лог-файла (nginx -s reopen, systemctl reload myapp) приложение продолжает писать в уже переименованный и заброшенный файл access.log.1, а новый access.log остаётся пустым.

directory vs default: где искать проблему

СимптомВероятная причинаПроверка
Правило не срабатывает вообщеСинтаксическая ошибка в конфигеlogrotate -d покажет ошибку парсинга
Файл ротируется, но не сжимаетсяДиректива compress отсутствует или закомментированаПроверить итоговый конфиг построчно
Новый файл пустой, старый растётПриложение не переоткрыло дескрипторПроверить наличие и содержимое postrotate
«insecure permissions»Права каталога логов слишком открытыеls -ld /var/log/имя-каталога

Когда logrotate не подходит

  • Приложение уже пишет логи через journald — тогда ротацией и хранением занимается journalctl --vacuum-size/--vacuum-time, а не logrotate, дублировать оба механизма избыточно.
  • Нужна централизованная агрегация логов с нескольких серверов и полнотекстовый поиск — logrotate только локально управляет файлами, для агрегации нужен стек вроде Grafana Loki.
  • Логи должны ротироваться по размеру в реальном времени, а не раз в сутки по крону — logrotate запускается по расписанию cron, а не следит за файлом непрерывно; для мгновенной ротации по размеру нужен инструмент вроде logrotate с более частым запуском или приложение с собственной ротацией.
  • Контейнеризированное приложение пишет логи в stdout, а не в файл — ротацией stdout-логов управляет сам движок контейнеров через драйвер логирования (json-file с лимитом размера), а не logrotate внутри контейнера.

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

  1. Проверьте синтаксис без реальной ротации: logrotate -d /etc/logrotate.d/nginx — в выводе не должно быть строк с error.
  2. Принудительно выполните ротацию: logrotate -f /etc/logrotate.d/nginx и убедитесь, что появился файл вроде access.log.1.gz.
  3. Проверьте, что приложение продолжает писать в новый файл, а не в старый: tail -f /var/log/nginx/access.log должен показывать новые запросы сразу после ротации.
  4. Проверьте статус последнего запуска: cat /var/lib/logrotate/status | grep nginx должен показывать сегодняшнюю дату.

Освобождение места на диске от уже накопленных старых логов, включая экстренную очистку без правки конфигов, разобрано отдельно в статье про logrotate на VPS. Для логов systemd-сервисов без отдельных файлов на диске см. статью про journalctl и rsyslog.

Проверить существующие правила

# Посмотреть все конфиги logrotate
ls /etc/logrotate.d/

# Протестировать без реальной ротации
sudo logrotate --debug /etc/logrotate.conf

Создать правило для своего приложения

# /etc/logrotate.d/myapp
/var/log/myapp/*.log {
    daily           # Ротация каждый день
    missingok       # Не ошибаться если файл отсутствует
    rotate 14       # Хранить 14 архивов
    compress        # Сжать gzip
    delaycompress   # Не сжимать последний архив
    notifempty      # Не ротировать пустые файлы
    create 0640 www-data www-data  # Права нового файла
    postrotate
        systemctl reload nginx > /dev/null 2>&1 || true
    endscript
}

Параметры logrotate

ПараметрОписание
daily/weekly/monthlyПериод ротации
rotate NКоличество архивов
size 100MРотация по размеру
compressСжать gzip
maxage 30Удалять архивы старше 30 дней
sharedscriptspostrotate выполняется один раз

Принудительная ротация прямо сейчас

sudo logrotate --force /etc/logrotate.d/myapp
✅ Logrotate запускается ежедневно через cron (/etc/cron.daily/logrotate). Обычно ничего дополнительно настраивать не нужно.

Освобождение места от старых логов

# Найти большие лог-файлы
sudo find /var/log -name "*.log" -size +100M

# Очистить файл без удаления (процесс продолжает писать)
sudo truncate -s 0 /var/log/nginx/access.log

# Или через journald
sudo journalctl --vacuum-size=500M

du vs df: как быстро понять, где место

СимптомКоманда для диагностикиЧто показывает
df видит меньше свободного места, чем dulsof +L1Удалённые, но всё ещё открытые файлы
Непонятно, какой каталог самый тяжёлыйdu -h --max-depth=1 /var/log | sort -rhРазмер каждого подкаталога логов
Логи растут быстрее, чем ожидалосьwatch -n 5 'du -sh /var/log/nginx'Скорость прироста в реальном времени

Когда обычной ротации мало

  • Диск уже заполнен под завязку прямо сейчас, а не ротация нужна на будущее — logrotate --force не поможет мгновенно, если виноваты открытые удалённые файлы; нужно сначала перезапустить держащие их процессы.
  • Логов накапливается больше, чем позволяет держать диск даже со сжатием — нужен вынос логов на отдельный том, в объектное хранилище или в централизованную систему вроде Grafana Loki, а не более агрессивная ротация на том же диске.
  • Нужно найти конкретную причину аномального роста логов, а не просто освободить место — это уже задача анализа самих логов на ошибки и подозрительный трафик, а не ротации.
Статья помогла?
← Назад в базу знаний Задать вопрос поддержке