Logrotate — стандартний інструмент Linux для керування лог-файлами. Автоматично архівує, стискає та видаляє старі логи за розкладом.
Як працює logrotate
- Запускається через cron (
/etc/cron.daily/logrotate) - Читає конфіги з
/etc/logrotate.confта/etc/logrotate.d/ - Для кожного логу застосовує правила: rotate, compress, delete
Конфіг для Nginx
sudo nano /etc/logrotate.d/nginx
/var/log/nginx/*.log {
daily
missingok
rotate 14
compress
delaycompress
notifempty
create 0640 www-data adm
sharedscripts
postrotate
nginx -s reopen
endscript
}
Конфіг для вашого застосунку
sudo nano /etc/logrotate.d/myapp
/var/www/myapp/logs/*.log {
weekly
rotate 8
compress
delaycompress
missingok
notifempty
create 0644 www-data www-data
}
Тестування та запуск
# Тест без реального виконання
sudo logrotate -d /etc/logrotate.d/nginx
# Примусовий запуск
sudo logrotate -f /etc/logrotate.conf
# Перевірити статус
sudo cat /var/lib/logrotate/status
| Директива | Значення |
|---|---|
| daily/weekly/monthly | Частота ротації |
| rotate N | Зберігати N архівів |
| compress | Стискати gzip |
| missingok | Не видавати помилку, якщо файл відсутній |
df -h. Якщо /var заповнений — запустіть logrotate -f /etc/logrotate.conf примусово.Розбір типових помилок
Помилка error: skipping "/var/log/nginx/access.log" because parent directory has insecure permissions зʼявляється, якщо каталог з логами доступний на запис групі чи всім — logrotate з міркувань безпеки відмовляється працювати з такими шляхами, щоб хтось не підмінив лог символьним посиланням на системний файл.
error: skipping "/var/log/nginx/access.log" because parent directory has insecure permissions
(It's world writable or writable by group which is not "root")
Рішення — виставити права каталогу chmod 755 /var/log/nginx, а не розширювати список довірених груп у /etc/logrotate.conf: це діра в безпеці, а не обхід бага. Прапорець su у правилі (su www-data www-data) іноді використовують замість виправлення прав, але він лише змінює користувача, від імені якого logrotate виконує ротацію, і не скасовує перевірку безпеки самого каталогу.
Після налаштування лог все одно росте нескінченно, хоча правило начебто правильне. Часта причина — процес тримає старий файловий дескриптор відкритим навіть після ротації: без postrotate зі свіжим сигналом переоткриття лог-файлу (nginx -s reopen, systemctl reload myapp) застосунок продовжує писати у вже перейменований і покинутий файл access.log.1, а новий access.log лишається порожнім.
directory vs default: де шукати проблему
| Симптом | Ймовірна причина | Перевірка |
|---|---|---|
| Правило не спрацьовує взагалі | Синтаксична помилка в конфігу | logrotate -d покаже помилку парсингу |
| Файл ротується, але не стискається | Директива compress відсутня або закоментована | Перевірити підсумковий конфіг порядково |
| Новий файл порожній, старий росте | Застосунок не переоткрив дескриптор | Перевірити наявність і вміст postrotate |
| «insecure permissions» | Права каталогу логів занадто відкриті | ls -ld /var/log/назва-каталогу |
Коли logrotate не підходить
- Застосунок уже пише логи через
journald— тоді ротацією і зберіганням займаєтьсяjournalctl --vacuum-size/--vacuum-time, а не logrotate, дублювати обидва механізми надлишково. - Потрібна централізована агрегація логів з кількох серверів і повнотекстовий пошук — logrotate лише локально керує файлами, для агрегації потрібен стек на кшталт Grafana Loki.
- Логи мають ротуватися за розміром у реальному часі, а не раз на добу за кроном — logrotate запускається за розкладом cron, а не стежить за файлом безперервно; для миттєвої ротації за розміром потрібен інструмент на кшталт
logrotateз частішим запуском або застосунок з власною ротацією. - Контейнеризований застосунок пише логи в stdout, а не у файл — ротацією stdout-логів керує сам рушій контейнерів через драйвер логування (
json-fileз лімітом розміру), а не logrotate всередині контейнера.
Перевірка результату
- Перевірте синтаксис без реальної ротації:
logrotate -d /etc/logrotate.d/nginx— у виводі не повинно бути рядків зerror. - Примусово виконайте ротацію:
logrotate -f /etc/logrotate.d/nginxі переконайтесь, що зʼявився файл на кшталтaccess.log.1.gz. - Перевірте, що застосунок продовжує писати в новий файл, а не в старий:
tail -f /var/log/nginx/access.logмає показувати нові запити одразу після ротації. - Перевірте статус останнього запуску:
cat /var/lib/logrotate/status | grep nginxмає показувати сьогоднішню дату.
Звільнення місця на диску від уже накопичених старих логів розібрано окремо в статті про logrotate на VPS. Для логів systemd-сервісів без файлів на диску див. статтю про journalctl і rsyslog.
Перевірити наявні правила
# Переглянути всі конфіги logrotate
ls /etc/logrotate.d/
# Протестувати без реальної ротації
sudo logrotate --debug /etc/logrotate.conf
Створити правило для свого застосунку
# /etc/logrotate.d/myapp
/var/log/myapp/*.log {
daily # Ротація щодня
missingok # Не видавати помилку, якщо файл відсутній
rotate 14 # Зберігати 14 архівів
compress # Стиснути gzip
delaycompress # Не стискати останній архів
notifempty # Не ротувати порожні файли
create 0640 www-data www-data # Права нового файлу
postrotate
systemctl reload nginx > /dev/null 2>&1 || true
endscript
}
Параметри logrotate
| Параметр | Опис |
|---|---|
| daily/weekly/monthly | Період ротації |
| rotate N | Кількість архівів |
| size 100M | Ротація за розміром |
| compress | Стиснути gzip |
| maxage 30 | Видаляти архіви старші 30 днів |
| sharedscripts | postrotate виконується один раз |
Примусова ротація прямо зараз
sudo logrotate --force /etc/logrotate.d/myapp
Звільнення місця від старих логів
# Знайти великі лог-файли
sudo find /var/log -name "*.log" -size +100M
# Очистити файл без видалення (процес продовжує писати)
sudo truncate -s 0 /var/log/nginx/access.log
# Або через journald
sudo journalctl --vacuum-size=500M
du проти df: як швидко зрозуміти, де місце
| Симптом | Команда для діагностики | Що показує |
|---|---|---|
| df бачить менше вільного місця, ніж du | lsof +L1 | Видалені, але все ще відкриті файли |
| Незрозуміло, який каталог найважчий | du -h --max-depth=1 /var/log | sort -rh | Розмір кожного підкаталогу логів |
| Логи ростуть швидше, ніж очікувалося | watch -n 5 'du -sh /var/log/nginx' | Швидкість приросту в реальному часі |
Коли звичайної ротації мало
- Диск уже заповнений вщент прямо зараз, а не ротація потрібна на майбутнє —
logrotate --forceне допоможе миттєво, якщо винні відкриті видалені файли; потрібно спершу перезапустити процеси, що їх тримають. - Логів накопичується більше, ніж дозволяє тримати диск навіть зі стисненням — потрібне винесення логів на окремий том, в обʼєктне сховище або в централізовану систему на кшталт Grafana Loki, а не агресивніша ротація на тому самому диску.
- Потрібно знайти конкретну причину аномального росту логів, а не просто звільнити місце — це вже задача аналізу самих логів на помилки і підозрілий трафік, а не ротації.