line — заметки на полях

Ротация логов своих сервисов через logrotate

14 августа 2025

Системные логи в Debian и Ubuntu ротируются сами, а вот всё, что пишет свои файлы в /var/log/имя-сервиса/, обычно остаётся без присмотра — до того дня, когда кончается место. Ниже — конфиг, который я копирую из проекта в проект, и пара мест, где легко ошибиться.

Базовый конфиг

Файл кладётся в /etc/logrotate.d/, имя — любое:

/var/log/myapp/*.log {
    daily
    rotate 14
    compress
    delaycompress
    missingok
    notifempty
    create 0640 myapp adm
    sharedscripts
    postrotate
        systemctl kill -s HUP myapp.service >/dev/null 2>&1 || true
    endscript
}

Что здесь важно:

  • rotate 14 вместе с daily — две недели истории. Старше удаляется.
  • delaycompress — вчерашний файл остаётся несжатым. Это спасает, если сервис ещё какое-то время пишет в старый дескриптор, и просто удобно для less.
  • notifempty — пустые файлы не ротируются, не плодим нулевые архивы.
  • sharedscripts — postrotate выполнится один раз на весь шаблон, а не для каждого файла.

create или copytruncate

По умолчанию logrotate переименовывает файл и создаёт новый (create). Сервис при этом продолжает писать в переименованный файл, пока не переоткроет его — для этого и нужен сигнал в postrotate. Большинство демонов умеют переоткрывать логи по HUP или USR1; что именно — смотрите в документации сервиса.

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

Проверка без ожидания ночи

Сухой прогон показывает, что logrotate собирается сделать, и ничего не трогает:

logrotate -d /etc/logrotate.d/myapp

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

logrotate -f /etc/logrotate.d/myapp

Когда файл ротировался в последний раз, записано в /var/lib/logrotate/status. В современных Ubuntu logrotate запускает не cron, а logrotate.timer — посмотреть расписание можно через systemctl list-timers logrotate.timer.

Типичные ошибки

  • Права на каталог. Если /var/log/myapp доступен на запись не только root, logrotate откажется работать и попросит директиву su myapp adm.
  • Забытый postrotate при create: новый файл создаётся пустым, а сервис неделями пишет в .log.1, который потом сжимается и удаляется.
  • Два конфига на один и тот же файл — logrotate ругнётся на дубликат и пропустит оба.