Ротация логов своих сервисов через logrotate
Системные логи в 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 ругнётся на дубликат и пропустит оба.