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

logrotate для своих демонов

Логи демона разрастаются, а ротации нет — файл достигает десятков гигабайт, диск забивается, мониторинг ругается. systemd-journald и syslog-ng умеют вращать сами, но если у тебя свой демон пишет напрямую в файл, ротацию несёт logrotate. Вот как его настроить под конкретный сервис.

Зачем писать свой конфиг logrotate

Пакеты из репозитория обычно ставят конфиг в /etc/logrotate.d/, но для自建 демонов или собранных из исходников его нет. Без конфига файл растёт бесконтрольно. logrotate запускается через systemd-таймер (logrotate.timer) или cron и читает все файлы из /etc/logrotate.d/. Достаточно создать один файл — и цикл ротации заработает.

Примечание

Проверь, установлен ли пакет logrotate и активен ли таймер: systemctl status logrotate.timer. В большинстве дистрибутивов он включён по умолчанию.

copytruncate vs create — когда что использовать

Это два принципиально разных подхода к переименованию и созданию нового файла.

copytruncatecreate
МеханизмКопирует текущий файл, обрезает оригинал на местеПереименовывает старый, создаёт новый с нужными правами
ПриложениеНе нужно перезапускатьНужно уметь открывать новый файл (обычно через SIGHUP или copytruncate не нужен)
Риск потери строкДа — между копированием и обрезкой новые записи могут попасть в «дыру»Минимальный — атомарное переименование
Когда использоватьДемон не умеет переоткрывать файл (например, написан на Go без сигналов)Демон поддерживает SIGHUP или systemd-notify
Предупреждение

copytruncate — это компромисс. Строки, записанные между cp и truncate, теряются. Для высоконагруженных сервисов это может означать сотни потерянных строк в секунду.

Если демон умеет получать сигнал — используй create и перезапускай через postrotate.

delaycompress и как он влияет на цепочку архивов

По умолчанию logrotate сжимает ротированный файл сразу в тот же цикл. Проблема: если демон ещё пишет в старый файл (или ещё не переоткрыл новый), сжатие ломает всё.

delaycompress откладывает сжатие на один цикл. Цепочка выглядит так:

app.log          ← текущий
app.log.1        ← ротированный, ещё не сжат
app.log.2.gz     ← сжатый, два цикла назад
app.log.3.gz     ← сжатый, три цикла назад

Без delaycompress переход выглядит жёстче: app.log сразу становится app.log.1.gz, и если демон ещё пишет в app.log через дескриптор, данные идут в сжатый архив — или теряются.

Подсказка

delaycompress имеет смысл только вместе с create и compress. С copytruncate он работает, но теряет смысл — ведь файл обрезается на месте, и сжатие можно делать сразу.

Интеграция с systemd notify

Если демон поддерживает sd_notify(3), можно не полагаться на postrotate с ручным перезапуском. systemd умеет перезапускать сервис по сигналу от logrotate.

В конфиге logrotate указываешь:

postrotate
    systemctl kill -s HUP my-daemon.service
endscript

Или, если демон слушает NOTIFY_SOCKET:

postrotate
    systemctl notify-reload my-daemon.service
endscript
Примечание

systemctl notify-reload доступен начиная с systemd 231. Отправляет RELOADING=1, а затем READY=1 — это стандартный механизм уведомления о перезагрузке конфигурации.

Для copytruncate postrotate обычно не нужен — обрезка файла на месте не требует участия демона.

Пример рабочего конфига

Допустим, демон my-app пишет в /var/log/my-app/app.log, поддерживает SIGHUP и sd_notify.

/var/log/my-app/app.log {
    daily
    rotate 14
    compress
    delaycompress
    missingok
    notifempty
    create 0640 myapp myapp
    postrotate
        systemctl notify-reload my-app.service >/dev/null 2>&1 || true
    endscript
}

Ключи:

ФлагЧто делает
dailyРотация каждый день
rotate 14Хранить 14 архивов
compressgzip-сжатие
delaycompressСжатие с задержкой на один цикл
missingokНе ругаться, если файла нет
notifemptyНе ротировать пустой файл
create 0640 myapp myappСоздать новый файл с нужными правами и владельцем
postrotateУведомить systemd о перезагрузке

Для теста без реального вращения:

logrotate -d /etc/logrotate.d/my-app

Флаг -d запускает в debug-режиме — покажет, что будет сделано, без изменений файлов.

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

После создания конфига первый запуск происходит только на следующий запуск таймера. Чтобы принудительно проверить — logrotate -f /etc/logrotate.d/my-app. Это немедленно ротирует файл, так что используй осторожно на проде.