Ubuntu 24.04: logrotate не ротує — одна помилка конфігурації, що постійно підводить людей

Було корисно?

Немає нічого кращого для «п’ятничного вечора», ніж заповнений диск тому, що один лог-файл вирішив перетворитися на базу даних. Ви перевіряєте /etc/logrotate.d/, бачите stanza для сервісу, але файл продовжує рости. Ніяких ротацій, ніякої компресії, ніякої пощади.

На Ubuntu 24.04 найпоширеніша причина, через яку logrotate «не ротує», — це не systemd, не баг ядра і не космічні промені. Це одна конфігураційна помилка: ви забули вказати тригер ротації (daily/weekly/monthly/hourly або size) і припустили, що якийсь глобальний дефолт вас виручить. Ні, не виручить. Logrotate прочитає вашу stanza, ввічливо знизить плечима і нічого не зробить — назавжди.

Одна помилка: немає тригера — немає ротації

Logrotate не ротує «бо файл існує» або «бо я написав конфіг». Він ротує, коли stanza каже йому коли ротація має відбутися. Це «коли» — тригер ротації:

  • daily, weekly, monthly, yearly або (на багатьох дистрибутивах) hourly
  • size (і родичі на кшталт minsize, maxsize)

Якщо ваш файл для конкретного сервісу в /etc/logrotate.d/ не містить тригера, ви покладаєтеся на успадкування. І саме тут люди отримують проблеми: глобальні дефолти Ubuntu можуть не задавати графік у такому вигляді, який застосовується до вашої stanza (або файл не читається, або ви ненавмисно його перевизначаєте). У підсумку: logrotate запускається, не бачить підстав для ротації, нічого не змінює і виходить з кодом 0, немов зробив вам послугу.

Як виглядає зла конфігурація

Це класична stanza «на вигляд нормальна в код-рев’ю, але падає в продакшені». Зверніть увагу на те, чого бракує:

cr0x@server:~$ sudo sed -n '1,120p' /etc/logrotate.d/myapp
/var/log/myapp/myapp.log {
  rotate 7
  compress
  missingok
  notifempty
  create 0640 myapp adm
  postrotate
    systemctl kill -s HUP myapp.service
  endscript
}

Цей конфіг має rotate 7, що лише каже «зберігати сім старих логів» якщо ротація відбувається. Це не каже, коли ротація має відбутися. Якщо ви не вкажете daily (або подібне) чи size, logrotate не зможе ухвалити рішення про ротацію.

Як виглядає виправлена конфігурація

Додайте явний тригер. Виберіть один. Не змушуйте читача гадати.

cr0x@server:~$ sudo sed -n '1,120p' /etc/logrotate.d/myapp
/var/log/myapp/myapp.log {
  daily
  rotate 7
  compress
  missingok
  notifempty
  create 0640 myapp adm
  postrotate
    systemctl kill -s HUP myapp.service
  endscript
}

Якщо ви віддаєте перевагу ротації за розміром (часто краще для говірких додатків):

cr0x@server:~$ sudo sed -n '1,120p' /etc/logrotate.d/myapp
/var/log/myapp/myapp.log {
  size 200M
  rotate 10
  compress
  delaycompress
  missingok
  notifempty
  create 0640 myapp adm
}

Зробіть тригер явним, навіть якщо вам здається, що він «очевидний». У продакшені очевидні припущення проходять аудит.

План швидкої діагностики (перший/другий/третій)

Коли logrotate «не ротує», потрібно швидко знайти вузьке місце: чи це розклад, парсинг, умова придатності, дозволи або провал postrotate?

Перший крок: підтвердіть, що logrotate взагалі викликається

  • Перевірте статус systemd timer/service і час останнього запуску.
  • Перегляньте журнал (journal) на предмет запусків logrotate і помилок.

Другий крок: запустіть logrotate в режимі відладки для конкретного конфига

  • Використайте -d (debug) і -v (verbose), щоб побачити дерево рішень.
  • Шукайте рядки на кшталт «log does not need rotating» і причину цього.

Третій крок: перевірте state-файл і логіку тригера

  • Перегляньте /var/lib/logrotate/status (або варіант дистрибутива), щоб побачити, що logrotate думає про останню ротацію.
  • Переконайтеся, що ваша stanza містить тригер (daily/weekly/size тощо).
  • Підтвердіть, що шляхи до файлів збігаються з реальністю (включно з шаблонами) і що дозволи дозволяють ротацію.

Якщо робити лише одну річ: запустіть logrotate з -d -v і читайте його як «чорний ящик» польоту. Зазвичай він соромно відвертий.

Як logrotate насправді вирішує, коли ротація потрібна (реальність Ubuntu 24.04)

Робота logrotate проста: для кожного лог-файлу визначити, чи потрібна ротація; якщо так — перейменувати/обрізати/скопіювати, за потреби стиснути і виконати скрипти. Диявол — у state-файлі та тригерах.

Планування в Ubuntu 24.04: таймери systemd, а не cron

У сучасному Ubuntu logrotate зазвичай запускається через systemd timer (а не класичний cron.daily). Це змінює місце пошуку при відладці «взагалі не запускається». Це також змінює поведінку при «пропущених» запусках: таймери можуть надолужити залежно від налаштувань.

State-файл — це пам’ять, якій довіряє logrotate

Logrotate не є демоном реального часу. Він запускається, ухвалює рішення і завершується. Щоб уникнути ротації всього щоразу, він зберігає часові мітки останньої ротації в state-файлі (зазвичай /var/lib/logrotate/status). Якщо в цьому файлі записано, що лог ротувався «сьогодні», stanza з daily не ротує його просто тому, що ви занепокоєні.

Тригери не опційні

Logrotate не виводить розклад ротації з rotate N, compress чи create. Це — дії. Тригери — окремі. Відсутній тригер — тихий режим відмови, тому що це не «синтаксична помилка». Це просто «жодна умова не виконана».

Парафразуючи ідею від Richard Cook: «Успіх ховає гострі краї системи; невдача виявляє, як робота дійсно відбувається». Ось так виглядає відладка logrotate в одному реченні.

Жарт №1: Logrotate як чергування шринерів: якщо ніколи не прописати графік, хтось усе одно постраждає — просто не програмне забезпечення.

Практичні задачі: команди, виводи, рішення (12+)

Нижче — конкретні завдання, які я використовую в інцидент-реперэхенні. Кожне включає: команду, що означає її вивід, і яке рішення з цього випливає.

Задача 1: Підтвердити, що таймер існує і ввімкнений

cr0x@server:~$ systemctl status logrotate.timer
● logrotate.timer - Daily rotation of log files
     Loaded: loaded (/usr/lib/systemd/system/logrotate.timer; enabled; preset: enabled)
     Active: active (waiting) since Sat 2025-12-28 07:10:22 UTC; 2h 14min ago
    Trigger: Sun 2025-12-29 00:00:00 UTC; 14h left
   Triggers: ● logrotate.service

Значення: Якщо він увімкнений і «Active (waiting)», планування, ймовірно, в порядку.

Рішення: Якщо він відключений/відсутній — спочатку виправте планувальник. Якщо ввімкнений — переходьте до перевірки виконання сервісу і журналу.

Задача 2: Підтвердити останній запуск сервісу і код виходу

cr0x@server:~$ systemctl status logrotate.service
● logrotate.service - Rotate log files
     Loaded: loaded (/usr/lib/systemd/system/logrotate.service; static)
     Active: inactive (dead) since Sat 2025-12-28 00:00:04 UTC; 9h ago
    Process: 1042 ExecStart=/usr/sbin/logrotate /etc/logrotate.conf (code=exited, status=0/SUCCESS)

Значення: Статус 0 означає, що logrotate не впав; він все одно міг не зробити ротацію.

Рішення: Якщо статус ненульовий — перевірте журнали; якщо успішний — переходьте в режим відладки, щоб дізнатися, чому він пропустив ротацію.

Задача 3: Переглянути журнал на повідомлення logrotate

cr0x@server:~$ journalctl -u logrotate.service -n 50 --no-pager
Dec 28 00:00:01 server systemd[1]: Starting logrotate.service - Rotate log files...
Dec 28 00:00:04 server systemd[1]: logrotate.service: Deactivated successfully.
Dec 28 00:00:04 server systemd[1]: Finished logrotate.service - Rotate log files.

Значення: Тут немає помилок, але й немає деталей. Це нормально; logrotate виводить деталі лише у verbose/debug режимі.

Рішення: Далі запустіть ручну відладку.

Задача 4: Імітація (dry-run) logrotate з verbose + debug

cr0x@server:~$ sudo logrotate -d -v /etc/logrotate.conf
reading config file /etc/logrotate.conf
including /etc/logrotate.d
reading config file /etc/logrotate.d/myapp
Handling 1 logs
rotating pattern: /var/log/myapp/myapp.log  after 1 days (7 rotations)
empty log files are not rotated, old logs are removed
considering log /var/log/myapp/myapp.log
  log does not need rotating (log has been already rotated)

Значення: Це показує, що logrotate думає про тригер («after 1 days») і чому він пропускає («already rotated»).

Рішення: Якщо рядок тригера відсутній або дивний — перевірте stanza. Якщо «already rotated» — перевірте state-файл.

Задача 5: Відладка конкретного файлу (вузький обсяг)

cr0x@server:~$ sudo logrotate -d -v /etc/logrotate.d/myapp
reading config file /etc/logrotate.d/myapp
error: /etc/logrotate.d/myapp:2 unknown option 'rotato'

Значення: Персоніфікована відладка швидко виявляє опечатки та помилки парсингу.

Рішення: Виправте синтаксичні помилки, перш ніж ганятися за поведінкою під час виконання.

Задача 6: Перевірити, чи stanza містить тригер (перевірка «однієї помилки»)

cr0x@server:~$ sudo egrep -n 'daily|weekly|monthly|yearly|hourly|size|minsize|maxsize' /etc/logrotate.d/myapp || echo "NO TRIGGER FOUND"
NO TRIGGER FOUND

Значення: Ключові слова тригера не знайдені. Це класичний випадок «rotate, але ніколи не ротується».

Рішення: Додайте daily або size явно і знову запустіть відладку.

Задача 7: Переглянути запис у state-файлі для вашого логу

cr0x@server:~$ sudo grep -F '/var/log/myapp/myapp.log' /var/lib/logrotate/status
"/var/log/myapp/myapp.log" 2025-12-28-0:0:0

Значення: Logrotate вважає, що ротація відбулася опівночі сьогодні. Якщо ви очікували, що він має ротацію зараз — проблема у вашому очікуванні.

Рішення: Якщо мітка часу неправильна, дослідіть зміну часу, корупцію state-файлу або дублювання шляхів. Не видаляйте state-файл необережно в продакшені.

Задача 8: Перевірити реальний розмір файлу та час зміни

cr0x@server:~$ ls -lh --time-style=long-iso /var/log/myapp/myapp.log
-rw-r----- 1 myapp adm 12G 2025-12-28 09:19 /var/log/myapp/myapp.log

Значення: Файл величезний і все ще пишеться. Якщо ви використовуєте лише часову ротацію, ви можете бути «праві», але операційно — приречені.

Рішення: Розгляньте size або maxsize поряд з часовими тригерами.

Задача 9: Перевірити власника логу і дозволи директорії

cr0x@server:~$ namei -l /var/log/myapp/myapp.log
f: /var/log/myapp/myapp.log
drwxr-xr-x root root /
drwxr-xr-x root root var
drwxrwxr-x root syslog log
drwxr-x--- myapp adm myapp
-rw-r----- myapp adm myapp.log

Значення: Директорія логів недоступна для «others»; logrotate зазвичай запускається від root, тож це нормально. Але якщо ви налаштували su неправильно, дозволи можуть блокувати ротацію.

Рішення: Якщо дозволи не дозволяють перейменовувати/створювати — виправте власника/режим або використайте правильну директиву su user group.

Задача 10: Виявити збій postrotate (прихована причина, чому нічого не змінюється)

cr0x@server:~$ sudo logrotate -v /etc/logrotate.d/myapp
reading config file /etc/logrotate.d/myapp
rotating pattern: /var/log/myapp/myapp.log  after 1 days (7 rotations)
considering log /var/log/myapp/myapp.log
  log needs rotating
rotating log /var/log/myapp/myapp.log, log->rotateCount is 7
renaming /var/log/myapp/myapp.log to /var/log/myapp/myapp.log.1
creating new /var/log/myapp/myapp.log mode = 0640 uid = 123 gid = 4
running postrotate script
error: error running shared postrotate script for '/var/log/myapp/myapp.log '

Значення: Ротація могла відбутися, але ваш крок сигналу/перезавантаження не спрацював. Деякі додатки продовжують писати в старий inode; інші потребують HUP, щоб відкрити логи заново.

Рішення: Виправте postrotate; інакше ви «ротуєте», але диск усе одно заповнюється, бо процес пише в непосилений дескриптор файлу.

Задача 11: Перевірити ситуацію «видалено, але все ще відкрите»

cr0x@server:~$ sudo lsof +L1 | head
COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF NLINK     NODE NAME
myapp    2210 myapp   7w   REG  252,0 12884901888     0  393502 /var/log/myapp/myapp.log (deleted)

Значення: Файл видалено/ротаційовано, але процес все ще пише у старий дескриптор. Використаний простір не звільниться.

Рішення: Виправте стратегію повторного відкриття файлів: HUP, reload або використайте copytruncate як останній засіб (з усвідомленням ризиків).

Задача 12: Перевірити, чи таймер реально спрацював у очікуваний час

cr0x@server:~$ systemctl list-timers --all | grep -F logrotate
Sun 2025-12-29 00:00:00 UTC 14h left Sat 2025-12-28 00:00:01 UTC 9h ago logrotate.timer logrotate.service

Значення: Останній запуск був опівночі; наступний — опівночі. Якщо ваш лог вибухнув о 09:00, добова ротація не врятує вас.

Рішення: Додайте пороги за розміром або підвищіть частоту запуску (обережно).

Задача 13: Примусова одноразова ротація (безпечно) для перевірки механіки

cr0x@server:~$ sudo logrotate -f -v /etc/logrotate.d/myapp
reading config file /etc/logrotate.d/myapp
rotating pattern: /var/log/myapp/myapp.log  forced from command line (7 rotations)
considering log /var/log/myapp/myapp.log
  log needs rotating
renaming /var/log/myapp/myapp.log to /var/log/myapp/myapp.log.1
creating new /var/log/myapp/myapp.log mode = 0640 uid = 123 gid = 4

Значення: Механіка працює: перейменування/створення/дозволи в порядку.

Рішення: Якщо примусова ротація працює, але планова — ні, це проблема тригера/state/планування, а не дозволів.

Задача 14: Перевірити порядок include і чи читається ваш файл взагалі

cr0x@server:~$ sudo grep -nE '^(include|#include)|/etc/logrotate\.d' /etc/logrotate.conf
12:include /etc/logrotate.d

Значення: Якщо include відсутній, файли в /etc/logrotate.d не матимуть значення.

Рішення: Відновіть рядок include, якщо хтось «спростив» глобальний конфіг.

Задача 15: Перевірити парсинг конфига без виконання ротацій (саніті-чек)

cr0x@server:~$ sudo logrotate -d /etc/logrotate.conf | tail -n 20
considering log /var/log/myapp/myapp.log
  Now: 2025-12-28 09:24
  Last rotated at 2025-12-28 00:00
  log does not need rotating

Значення: Режим відладки показує «Now» і «Last rotated». Якщо ці значення дивні — йдіть по сліду часу/state.

Рішення: Якщо «Last rotated» у майбутньому — ймовірно, у вас розбіжність часу, відновлена VM-знімка або скопійований state-файл.

Поширені помилки: симптом → коренева причина → виправлення

1) «Я вказав rotate 30, але нічого не ротується»

Симптом: Файл росте нескінченно; logrotate повідомляє про успіх; немає старих файлів.

Коренева причина: Відсутня директива тригера (daily/weekly/size).

Виправлення: Додайте явний тригер. Для високонавантажених логів віддавайте перевагу size; для відповідності політикам збереження — часові тригери.

2) «Logrotate запускається, але каже ‘log does not need rotating’, хоч файл величезний»

Симптом: 20G лог; відладка каже, що ротація не потрібна.

Коренева причина: Ви налаштували лише daily і він вже ротував сьогодні; або state-файл каже, що ротація була.

Виправлення: Додайте maxsize або size. Або ротуйте частіше. Не воюйте зі state-файлом; проектуйте під нього.

3) «Ротації є, але використання диску не падає»

Симптом: Бачите myapp.log.1, але df все одно страшний.

Коренева причина: Процес тримає відкритим старий (deleted) inode; логи йдуть у файл з позначкою (deleted).

Виправлення: Переконайтеся, що процес повторно відкриває лог (HUP/reload), або використайте copytruncate, якщо додаток не може перестворити файл (усвідомлюючи ризик втрати рядків).

4) «Ручний logrotate -f працює, але запланований — ні»

Симптом: Примусова ротація працює; таймер щоденний нічого не робить.

Коренева причина: План не спрацьовує, таймер відключений, include відсутній або state каже, що вже ротація була.

Виправлення: Перевірте systemctl list-timers, підтвердіть, що /etc/logrotate.conf включає /etc/logrotate.d, перегляньте /var/lib/logrotate/status.

5) «Помилки ротації: permission denied»

Симптом: У verbose/debug видно помилку перейменування/створення.

Коренева причина: Неправильний власник/режим; директорія логів не записувана; некоректне використання su; або логи на нестандартному монтуванні з обмеженнями.

Виправлення: Виправте файлові дозволи. Якщо використовуєте su, впевніться, що user/group відповідають власнику файлу і директорії.

6) «Ротація є, але додаток перестає логувати»

Симптом: Після ротації файл пустий і додаток продовжує працювати.

Коренева причина: Додаток продовжує писати в старий fd; новий файл створено, але не використовується; postrotate не сигналить правильно.

Виправлення: Використайте коректну дію в postrotate: HUP, reload або специфічну команду reopen. Перевірте через lsof.

7) «Я використав шаблони (wildcards) і нічого не відбувається»

Симптом: Stanza на кшталт /var/log/myapp/*.log; ротацій не відбувається.

Коренева причина: Шаблон нічого не збігає; дозволи перешкоджають розширенню glob; або логи лежать у іншій директорії, ніж ви думаєте.

Виправлення: Підтвердіть збіги через ls. Для критичних логів використовуйте явні шляхи.

8) «Після відновлення образу, logrotate не ротує дні»

Симптом: Відладка каже, що остання ротація в майбутньому.

Коренева причина: State-файл скопійований з іншої машини/часу; відновлено VM-знімок; зміни часу.

Виправлення: Спочатку виправте час. Потім акуратно відкорегуйте запис у state-файлі (редагуйте лише потрібний рядок) або разово форсуйте ротацію -f і перевірте оновлення state.

Три корпоративні міні-історії з практики

Інцидент №1: хибне припущення («rotate 14 означає кожні 14 днів, так?»)

Середній SaaS мав внутрішній сервіс, що виводив JSON-логи. Він працював місяцями, бо ніхто не дивився на використання кореневого файлового системи вузла, поки щось не спрацювало. Сервіс отримав фічу, яка подвоїла обсяг логів — нічого драматичного, просто більше полів контексту.

Через два тижні інженер на чергуванні побачив, що диск на продакшн-вузлі зайнятий на 97%. Вони знайшли /var/log/internal/worker.log розміром десятки гігабайт. Там була stanza з rotate 14, compress, create і notifempty. Виглядало «налаштовано». Всі припустили, що «rotate 14» означає «рутувати кожні 14 днів». Ні.

Таймер працював. Logrotate виходив з кодом 0. Ніяких ротацій. Конфіг не мав daily, ні weekly, ні size. Це була політика без тригера — наче написати «зберігати 14 бекапів», але ніколи не запускати бекап.

Вони додали daily і maxsize 500M, разово форснули ротацію для полегшення ситуації, а потім відкоригували моніторинг, щоб попереджати зростання обсягу логів до критичних значень.

Постмортем був чемним, але різким: «Ми припустили, що logrotate має дефолтний графік. Ми не тестували поведінку ротації в стейджингу при реалістичному обсязі логів.» Історія повторюється.

Інцидент №2: оптимізація, яка відпалилася боком (copytruncate скрізь)

Регульоване підприємство мало легасі Java-додаток, який не пере відкрив лог на HUP. Хтось «вирішив» це багато років тому через copytruncate. Це працювало настільки добре, що стало дефолтом для нових сервісів — copytruncate для всього і завжди.

Потім компанія перенесла навантаження на швидкі NVMe і збільшила пропускну здатність. Найбільш завантажений сервіс почав писати кілька гігабайт на годину. Ротація стала настільки довгою, що вікно копіювання стало критичним, і вони почали втрачати рядки логів. Не «можливо», а доведено. Аудит-трейл мав прогалини саме на межі ротацій.

Гірше: стиснення запускалося одразу і різко піднімало навантаження на CPU у пікові години. «Оптимізація» створила перфомансний обрив: під час ротації CPU підскакував, зростала латентність, виникали ретраї, що давало ще більше логів і ще більші ротації — самопідсилювальне коло.

Вони відкотилися: перейшли на перейменування (rename-based rotation) і виправили додаток, щоб він коректно пере відкривав логи на сигнал. Також додали delaycompress, щоб відкласти стиснення поза критичний момент. Це була не красива робота, але правильна.

Жарт №2: «Ми використовували copytruncate, щоб не міняти додаток» — це логінговий еквівалент латання дірки більшим швабром.

Інцидент №3: нудна практика, яка врятувала день (явні тригери + тестування)

Мала платформа команда обслуговувала десятки внутрішніх сервісів, переважно Go і Python, на Ubuntu. Вони мали звичку, яка здавалася надмірно педантичною: кожна stanza logrotate мала явний тригер і коментар, чому саме такий. Жодного успадкування. Кожна stanza: daily або size (іноді обидва через maxsize), завжди свідомо.

Також у них був пункт у чек-листі релізу: після розгортання нового сервісу запустити logrotate -d -v для його stanza і додати шматок виводу в запис про зміну. Це здавалося бюрократією, поки зміна базового образу не поміняла деякі глобальні дефолти і кілька сервісів не опинилися на нових вузлах.

Сервіси з явними тригерами ротаціювалися нормально. Сервіси, що покладалися на успадкування, поводилися дивно: деякі ротаціювали щотижня, коли очікували щоденно; деякі ротаціювали лише при досягненні дефолтного порогу розміру, якого ніхто не пам’ятав. Команда платформи не мала інциденту. Вони мали лише нудний вівторок.

Різниця не в магії. Вона в нудній практиці: зробити «коли рoтувати» явним і один раз протестувати поведінку, так само як ви тестуєте правило firewall чи бекап. Ось як виглядає професіоналізм в опс: запобігати сюрпризам, а не героїчно реагувати на них.

Цікаві факти та контекст (чому це повторюється)

  1. Logrotate старший за systemd. Він виріс у світі cron, і перехід на таймери systemd змінив місця, куди дивляться при відладці.
  2. State-файл — ядро пам’яті logrotate. Без нього часові ротації або ротаціювали б постійно, або довелося б покладатися на евристики файлової системи.
  3. rotate N — це збереження, а не розклад. Це найпоширеніша концептуальна помилка — слово «rotate» нівелює різницю між збереженням і тригером.
  4. Багато дистрибутивів включають глобальний конфіг з дефолтами. Люди припускають, що ці дефолти містять тригер. Іноді так; іноді ні; іноді ваша stanza їх перевизначає; іноді ваш файл взагалі не включено.
  5. Journald зменшив залежність деяких сервісів від файлових логів. Але багато додатків досі пишуть у файли (сумісність, відповідність або тому, що образ контейнера з 2016 року і ніхто не хоче чіпати).
  6. Copytruncate став популярним, бо «працює» з упертими додатками. Але він вводить гонки і потенційну втрату під навантаженням, бо запис може відбуватися під час копіювання.
  7. Раніше стиснення було достатньо дорогим, щоб планувати його окремо. На сучасних CPU воно дешевше, але все одно має значення при стисненні багатогігабайтних логів у пікові години.
  8. Перейменування логів атомарне; обрізання — ні. Підхід на основі перейменування відповідає поведінці Unix-файлових дескрипторів і зазвичай безпечніший, коли додатки коректно пере відкривають логи.
  9. Конфіги logrotate оманливо дозволяють багато чого. Багато неправильних налаштувань не є синтаксичними помилками; це логічні помилки, які призводять до «успішної бездіяльності».

Чек-листи / покроковий план

Покроково: запустити ротацію для одного проблемного логу

  1. Підтвердіть, що планування існує.

    cr0x@server:~$ systemctl status logrotate.timer
    ● logrotate.timer - Daily rotation of log files
         Loaded: loaded (/usr/lib/systemd/system/logrotate.timer; enabled; preset: enabled)
         Active: active (waiting) since Sat 2025-12-28 07:10:22 UTC; 2h 14min ago
        Trigger: Sun 2025-12-29 00:00:00 UTC; 14h left
       Triggers: ● logrotate.service

    Рішення: Якщо відключено — увімкніть. Якщо ввімкнено — продовжуйте.

  2. Доведіть, що ваш конфіг включено.

    cr0x@server:~$ sudo grep -n 'include /etc/logrotate.d' /etc/logrotate.conf
    12:include /etc/logrotate.d

    Рішення: Якщо відсутній — відновіть include і протестуйте знову.

  3. Запустіть відладку для цієї stanza.

    cr0x@server:~$ sudo logrotate -d -v /etc/logrotate.d/myapp | sed -n '1,120p'
    reading config file /etc/logrotate.d/myapp
    Handling 1 logs
    considering log /var/log/myapp/myapp.log
      log does not need rotating

    Рішення: Якщо він не згадує графік/розмір, ймовірно, тригер відсутній.

  4. Додайте явний тригер.

    Виберіть: часовий (daily) або за обсягом (size / maxsize). Для високонавантажених логів зазвичай кращий обсяг.

  5. Разово форсніть ротацію для перевірки механіки.

    cr0x@server:~$ sudo logrotate -f -v /etc/logrotate.d/myapp | tail -n 30
    considering log /var/log/myapp/myapp.log
      log needs rotating
    renaming /var/log/myapp/myapp.log to /var/log/myapp/myapp.log.1
    creating new /var/log/myapp/myapp.log mode = 0640 uid = 123 gid = 4

    Рішення: Якщо примусова ротація не вдається — виправте дозволи/шляхи перш ніж звинувачувати планування.

  6. Переконайтеся, що додаток пише в новий лог.

    cr0x@server:~$ sudo lsof /var/log/myapp/myapp.log | head
    COMMAND  PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
    myapp   2210 myapp   7w   REG  252,0   123456  401 /var/log/myapp/myapp.log

    Рішення: Якщо він все ще пише в видалений inode — виправте postrotate або поведінку додатка щодо повторного відкриття файлу.

Операційний чек-лист: що має бути в продакшн-grade stanza

  • Явний тригер: daily або size/maxsize.
  • Явне збереження: rotate N плюс compress і зазвичай delaycompress.
  • Правильне створення: create MODE USER GROUP або навмисне покладання на додаток (обирайте свідомо).
  • Безпечна стратегія повторного відкриття: postrotate сигнал/перезавантаження, перевірене через lsof.
  • Не покладатися на успадкування, якщо ви не протестували це і не зможете пояснити напівсонному співробітнику.
  • Обмеження за розміром для говірких сервісів: maxsize запобігає тому, щоб добова ротація була надто пізньою.

FAQ

1) Чому logrotate виходить з успіхом навіть коли нічого не ротує?

Тому що «жоден лог не потребує ротації» — це дійсний результат. Logrotate — це движок політики, не задача «обов’язково щось поротувати». Проблема виникає, коли ви очікували ротацію, але не вказали тригер або state/критерії кажуть «ще не настав час».

2) Чи ця «одна помилка конфігу» справді просто відсутність daily або size?

Так, у практичному сенсі: відсутність тригера (або помилка, коли люди думають, що rotate N — це тригер) — найпоширеніша причина тихої неротації. Синтаксичні помилки зазвичай голосно кричать; відсутні тригери шепочуть.

3) Чи слід використовувати часову або розмірну ротацію?

Для низького та помірного обсягу daily підходить. Для високого обсягу використовуйте size або maxsize (часто разом з daily), щоб не чекати опівночі, поки лог розбіжиться.

4) У чому різниця між size, minsize та maxsize?

size ротує, коли файл перевищує вказаний розмір (незалежно від часових критеріїв). minsize додає мінімальний розмір до часової ротації. maxsize примусово ротує при перевищенні розміру навіть якщо часові умови ще не виконані.

5) Коли варто використовувати copytruncate?

Коли додаток не може повторно відкрити логи і швидко виправити це неможливо. Це хак сумісності з компромісами: потенційна втрата рядків на межах ротації і додаткові I/O. Надавайте перевагу перейменуванню + сигналу/перевідкриттю для коректності.

6) Чому використання диску залишається високим після ротації?

Бо процес може продовжувати писати в видалений дескриптор файлу. Файлова система звільняє простір лише коли останній дескриптор закривається. Використайте lsof +L1 для виявлення і виправте повторне відкриття файлів.

7) Чи можу я видалити /var/lib/logrotate/status, щоб «скинути» все?

Можете, але це грубий інструмент. Це може спричинити несподівані ротації для багатьох логів при наступному запуску. Безпечніше: відредагувати лише проблемний запис або форсувати ротацію для конкретного конфига через logrotate -f і перевірити поведінку.

8) Чому моя stanza працює в одному середовищі, але ні в іншому?

Інші глобальні дефолти, інша поведінка include, інші таймери, інша власність файлів та інша поведінка додатків при повторному відкритті. Виправлення нудне: робіть тригери явними, тестуйте з -d -v і валідуйте через lsof.

9) Я додав daily, але ротація все одно не відбувається. Що далі?

Перевірте запис у state-файлі і вивід відладки. Якщо там «already rotated», то доведеться чекати до наступного дня. Якщо таймер не спрацьовує — виправте планування systemd. Якщо дозволи падають — виправте власника/режим або su.

10) Чи варто ротуувати логи щогодини на Ubuntu 24.04?

Тільки якщо це дійсно потрібно. Годинна ротація підвищує чекання (більше файлів, більше стиснення, більше метаданих). Якщо проблема в «диск заповнюється до півночі», maxsize часто кращий важіль.

Наступні кроки (що змінити в понеділок)

Якщо ви маєте справу з тим, що logrotate не ротує на Ubuntu 24.04, зробіть це в порядку:

  1. Зробіть тригер явним в кожній кастомній stanza: додайте daily або size/maxsize. Перестаньте покладатися на успадкування.
  2. Запустіть logrotate -d -v для саме того файлу, що вас цікавить, і прочитайте рядки з поясненням. Не гадіть.
  3. Перевірте запис у state-файлі для логу і підтвердіть, що він відповідає вашому очікуванню «останньої ротації». Спочатку виправте розбіжності часу.
  4. Перевірте поведінку повторного відкриття через lsof +L1. Якщо бачите (deleted), ваші ротації косметичні.
  5. Додайте обмеження за розміром для говірких сервісів. Добова ротація — це не система безпеки; це календарна подія.

Мета не просто «щоб логи ротаціювалися». Мета — «щоб логи ротаціювалися передбачувано, без втрати подій, без несподіваних стрибків CPU і без нічних викликів» — от стандарт.

← Попередня
MySQL vs MariaDB: тимчасові таблиці на диску — як зупинити їх назавжди
Наступна →
ZFS zpool iostat -w: як у реальному часі розпізнати шаблони навантаження

Залишити коментар