Что было. На Ubuntu Server 22.04 для логов приложения написали свой файл в /etc/logrotate.d/:
/srv/app/logs/*.log {
su appuser appgroup
weekly
rotate 6
compress
missingok
create 660 appuser appgroup
}
При запуске logrotate пропускал файлы: «skipping … because parent directory has insecure permissions (It’s world writable or writable by group which is not “root”)». После правок появилось «Permission denied».
Почему. logrotate работает от root, и с версии 3.8 он отказывается трогать файлы в каталоге, куда может писать кто-то кроме root (иначе владелец каталога мог бы подменить лог символической ссылкой и заставить root перезаписать произвольный файл). Директива su user group говорит logrotate выполнять ротацию от имени этого пользователя, и тогда каталог должен принадлежать ему (или его группе) и не быть доступным на запись остальным.
Что сделал автор. Поменял su appuser appgroup на su root root, после чего ротация заработала без ошибок. Подтверждено. Это рабочий, но не самый аккуратный вариант: root пишет в каталог приложения, а созданный файл получает владельца из create 660 appuser appgroup, так что приложение продолжает писать.
Как сделать правильно.
- Каталог логов должен принадлежать пользователю приложения:
chown appuser:appgroup /srv/app/logs && chmod 750 /srv/app/logs. Никаких777и группового доступа для посторонних групп. - В конфиге
su appuser appgroup: ротация выполняется от имени владельца, проверка безопасности проходит. - Приложение после ротации должно переоткрыть файл: либо
copytruncate(просто, но возможна потеря строки на границе), либоpostrotate systemctl kill -s HUP app.service endscript, если приложение понимает сигнал, либоpostrotate systemctl restart app.service endscriptкак крайняя мера. - Проверка без изменений:
logrotate -d /etc/logrotate.d/app(отладочный прогон) и принудительноlogrotate -f /etc/logrotate.d/app. - Состояние ротаций хранится в
/var/lib/logrotate/status: если файл ротировали недавно, следующая ротация будет только через период; для теста можно удалить строку файла из статуса.
Почему ротация «не работает вообще». На systemd-системах logrotate запускается таймером logrotate.timer раз в сутки, а не из cron: systemctl list-timers logrotate* и journalctl -u logrotate покажут запуски и ошибки. Часто вся конфигурация верна, а ошибка одна и относится к другому файлу, но из-за неё пропускается весь блок.
Директивы описаны в документации Ubuntu.