Перейти к содержимому

logrotate: автоматическая ротация и архивация логов

Логи приложений забивают диск за неделю, а rm *.log вручную — путь к проблемам. logrotate решает это сам: ротирует, сжимает и удаляет старые файлы по расписанию. Разберёмся, как это работает и как настроить за пять минут.

Как это устроено

logrotate вызывается через cron ежедневно. Конфиг по умолчанию живёт в /etc/logrotate.conf, а дополнительные конфиги подключаются из /etc/logrotate.d/. При ротации текущий файл переименовывается, создаётся новый пустой, старые копии сжимаются и нумеруются.

Цикл простой:

app.log        →  app.log.1      (сжатый: app.log.1.gz)
app.log.1.gz   →  app.log.2.gz
...
app.log.5.gz   →  удалён

Механизм работает через rename или mv, поэтому процесс должен держать дескриптор открытым. Если ротация не подхватывается приложением — получаете дублирование или пустой лог.

Структура конфигурации

# /etc/logrotate.conf — глобальные настройки
weekly          # ротация раз в неделю
rotate 4        # хранить 4 копии
compress        # сжимать старые логи
include /etc/logrotate.d/

Файлы из /etc/logrotate.d/ перекрывают глобальные значения для конкретных логов. Формат простой:

/путь/к/логу {
    директива значение
    ...
}

Директивы наследуются от глобального конфига, если не переопределены. Можно указать несколько путей через пробел или шаблон — это удобно для ротации всех логов приложения одним блоком.

Ключевые директивы

Базовые параметры, которые закрывают 90% задач:

ДирективаНазначениеПример
rotate Nсколько копий хранитьrotate 7
size Nразмер для триггера ротацииsize 100M
missingokне ошибка, если файла нет—
notifemptyпропустить пустой лог—
compressсжимать старые (по умолчанию gzip)—
dateextдата вместо номера в имени—
dateformatформат датыdateformat -%Y%m%d
postrotate ... endscriptкоманды после ротацииreload сервиса
prerotate ... endscriptкоманды до ротацииprepare директории

size отменяет weekly/monthly/daily, если задан. Ротация происходит когда файл достигает указанного размера И прошёл интервал. То есть size 100M при weekly — ротация не раньше недели и если файл больше 100М.

Примечание

dateext несовместим с длинными именами файлов на некоторых файловых системах. Если имя лога + суффикс даты выходит за 255 байт — logrotate упадёт.

Пример конфига для приложения

Допустим, у нас сервис myapp пишет в /var/log/myapp/. Конфиг:

/var/log/myapp/*.log {
    daily
    rotate 14
    size 50M
    missingok
    notifempty
    compress
    dateext
    dateformat -%Y%m%d-%s
    sharedscripts
    postrotate
        systemctl reload myapp > /dev/null 2>&1 || true
    endscript
}

sharedscripts гарантирует один вызов postrotate для всех ротируемых файлов, а не для каждого. Без него скрипт выполняется столько раз, сколько файлов подпало под ротацию.

Для Python-приложений с ротацией через стандартный library:

/var/log/myapp/app.log {
    su root myapp
    daily
    rotate 7
    size 200M
    missingok
    notifempty
    compress
    postrotate
        /usr/bin/pkill -HUP -f "python.*myapp" || true
    endscript
}

su меняет владельца процесса ротации — полезно, если приложение запущено под отдельным пользователем и права на логи ограничены.

Отладка и принудительный запуск

dry-run режим показывает что будет сделано без реальных действий:

logrotate -d /etc/logrotate.d/myapp

Вывод содержит каждое решение: какой файл переименовывается, какой сжимается, какие команды выполняются. Смотрите на строки renaming и running postrotate script.

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

logrotate -f /etc/logrotate.d/myapp

-f игнорирует время последней ротации и размеровые условия. Комбинация с -d — безопасный способ проверить перед продакшеном:

logrotate -d -f /etc/logrotate.d/myapp

Если нужно ротировать конкретный лог вне расписания, но с учётом условий — используйте state-файл:

# посмотреть состояние
cat /var/lib/logrotate/status

# временно сдвинуть время последней ротации
sed -i 's|/var/log/myapp/app.log.*|/var/log/myapp/app.log 2024-01-01-00:00:00|' /var/lib/logrotate/status
logrotate /etc/logrotate.d/myapp

Проверка синтаксиса без выполнения:

logrotate -d /etc/logrotate.conf

Если ошибок нет — вывод пустой (без -d) или показывает план действий (с -d).

Предупреждение

Не редактируйте /var/lib/logrotate/status вручную в продакшене без понимания формата. Одна ошибка — и logrotate решит что ротация уже прошла, пропустит все файлы до следующего запуска cron.

Настройка cron по умолчанию:

# /etc/cron.daily/logrotate
#!/bin/sh
test -x /usr/sbin/logrotate || exit 0
/usr/sbin/logrotate /etc/logrotate.conf

В большинстве дистрибутивов трогать этот файл не нужно. Если нужен запуск чаще раза в сутки — добавляйте в /etc/cron.hourly/ или пишите отдельный cron job.