Ви змінили конфігурацію. Ви вчинили відповідально. Ви навіть залишили коментар типу «тимчасово», який обов’язково залишиться там у 2027 році. Тепер служба не запускається, моніторинг присилає сповіщення, а systemctl status поводиться загадково.
Добра новина: Debian 13 разом із systemd дає все потрібне, щоб швидко вирішити проблему — якщо ви перестанете читати неправильні рядки журналу. Погана новина: більшість людей саме це й робить: приглядаються до останніх трьох рядків виводу та починають ритуальні жертви «кешу». Не робіть так. Читайте правильні рядки у правильному порядку — і ви виправите це за лічені хвилини.
Випадок №1: зміна конфігурації → служба не запускається (що насправді сталося)
Це найпоширеніший сценарій, який я бачу на Debian-системах: служба працює, хтось редагує конфігураційний файл, а потім перезапускає службу. Перезапуск не вдається. Людина на чергуванні відкриває systemctl status, бачить «failed with result ‘exit-code’» і починає гадати.
Виправлення майже завжди знаходиться у журналах, але не в тому місці, яке люди читають першим. Корисний рядок зазвичай:
- Ранніше, ніж рядок «Main process exited…»
- Від допоміжного процесу (наприклад,
ExecStartPre), який перевірив конфіг і вийшов - Або від самого демона, виведений один раз і похований під системними рядками systemd
Для випадку №1 уявіть типову службу з кроком перевірки конфігурації:
ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on;ExecStart=/usr/sbin/nginx -g daemon on; master_process on;
Перезапуск не вдається не тому, що systemd містичний, а тому, що передстартовий тест конфігурації виявив синтаксичну помилку, невірний шлях включення або проблему з правами доступу для файлу, на який посилаються. «Правильні рядки журналу» — це ті, що описують цю передстартову невдачу. Ваше завдання — витягти їх чисто, не тонути у невідповідних повідомленнях.
Жарт №1 (короткий, по темі): Перезапуск служби — це як пакування парашута: якщо пропустити перевірку, ви все одно дізнаєтеся, чи спрацювало.
Кілька фактів і історія, які пояснюють, чому журнали виглядають так
Розуміння того, чому Debian 13 поводиться саме так, робить вас швидшим під тиском. Ось конкретні факти, які важливі, коли служба відмовляється запускатися після зміни конфігурації:
- systemd став системою ініціалізації за замовчуванням у Debian з версії 8 (Jessie). Це стандартизувало керування службами та очікування від логів, але також змінило місця, куди люди дивляться за помилками.
- journald — це не текстовий файл. Журнали зберігаються в бінарному журналі й запитуються через
journalctl. Ви все ще можете переслати у syslog, але канонічним джерелом є журнал. systemctl status— це підсумок, а не розслідування. Воно показує обрізаний шматок журналу і високорівневий стан юніта. Це покликано спрямувати вас до глибших запитів, а не замінити їх.- systemd-юніти можуть мати кілька процесів перед запуском «справжнього» демона.
ExecStartPre, генератори, обгортки та файли середовища можуть упасти ще до того, як PID вашої служби з’явиться. - Коди виходу стандартизовані, але часто вводять в оману без контексту. «exit status 1» може означати «синтаксична помилка», «доступ заборонено» або «порт уже зайнятий». Потрібне повідомлення поряд із кодом.
- Багато демонів спроектовані так, щоб відмовлятись при некоректному конфігу швидко. Nginx, Postfix, HAProxy та інші навмисно відмовляються запускатись, якщо тести конфігурації не проходять — бо запуск з частковою чи некоректною конфігурацією гірший.
- Пакети Debian часто додають перевірки безпеки. Упакувальники часто включають передстартові валідації в юніти або скрипти-обгортки. Це гарна інженерія, але означає, що помилки можуть походити зі скриптів, про які ви не підозрювали.
- Порядок у журналах може вводити в оману. journald має часові позначки, але паралельний старт юнітів та кілька процесів можуть перемішувати повідомлення. «Останній рядок» не завжди є «причиною».
- Обмеження швидкості реальні. journald може лімітувати спамні служби; перша помилка записується, а наступні 500 можуть бути підсумовані. Якщо ви читаєте тільки підсумок, ви пропускаєте першу підказку.
Одна сформульована ідея, яку варто тримати в голові, правильно приписана: Gene Kim (парафраз): надійність покращується, коли ви будуєте швидкі цикли зворотного зв’язку і скорочуєте відстань між зміною та діагностикою.
Швидкий план діагностики (перші/другі/треті перевірки)
Це порядок, який переможе в продакшені. Він орієнтований на отримання кореневої причини за менше ніж п’ять хвилин, а не на створення ілюзії зайнятості.
Перше: підтвердьте, що systemd вважає за неуспіх (огляд юніта)
- Отримайте стан юніта, код виходу і яка фаза впала (передстарт чи основний запуск).
- Витягніть точну командну лінію, яку systemd виконав (включно з
ExecStartPre).
Друге: витягніть правильний фрагмент журналу (за часом і юнітом)
- Запитуйте логи для цього юніта, для останнього завантаження, з мінімальним шумом.
- Потім розширюйте часовий інтервал за потреби; не розширюйте спочатку область юніта.
- Шукайте перший змістовний рядок з помилкою, а не останній рядок «exited».
Третє: запустіть власну валідацію конфігурації вручну
- Більшість служб має режим «перевірити конфіг і вийти».
- Запустіть його точно так, як це робить systemd (той самий користувач, ті самі змінні середовища, той самий шлях до конфігу).
- Якщо валідація проходить вручну, але падає під systemd — підозрівайте права, файли середовища, AppArmor або відмінності робочого каталогу.
Четверте: вирішіть — виправити, відкотити чи тимчасово обійти
- Якщо це ясна синтаксична помилка: виправляйте її зараз і перезапустіть.
- Якщо невпевнено і продакшн палає: відкотіть до останньої відомо-робочої конфігурації і перезапустіть.
- Уникайте «тимчасових» обходів типу коментування валідаційних кроків, якщо ви не розумієте наслідків.
Практичні завдання: команди, очікуваний вивід і рішення (12+)
Ці завдання написані так, як насправді працює SRE: запустив команду, прочитав вивід, ухвалив рішення. Ніяких мотиваційних промов. Кожне завдання включає, що означає вивід і що робити далі.
Завдання 1: Перевірте статус юніта (але читайте його правильно)
cr0x@server:~$ systemctl status nginx.service --no-pager
● nginx.service - A high performance web server and a reverse proxy server
Loaded: loaded (/lib/systemd/system/nginx.service; enabled; preset: enabled)
Active: failed (Result: exit-code) since Mon 2025-12-30 10:14:03 UTC; 42s ago
Duration: 2.103s
Process: 21984 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=1/FAILURE)
CPU: 29ms
Dec 30 10:14:03 server nginx[21984]: nginx: [emerg] unexpected "}" in /etc/nginx/sites-enabled/app.conf:57
Dec 30 10:14:03 server systemd[1]: nginx.service: Control process exited, code=exited, status=1/FAILURE
Dec 30 10:14:03 server systemd[1]: nginx.service: Failed with result 'exit-code'.
Dec 30 10:14:03 server systemd[1]: Failed to start nginx.service - A high performance web server and a reverse proxy server.
Що це означає: Невдача сталася в ExecStartPre, до запуску демона nginx. Це помилка тесту конфігурації, а не аварійний збій у runtime.
Рішення: Не ганяйтеся за портами, PID-файлами чи лімітами ядра. Виправте рядок у конфігу, на який посилається повідомлення (app.conf:57), і знову запустіть тест конфігурації.
Завдання 2: Показати лише журнал для цього юніта (остання спроба, чисто)
cr0x@server:~$ journalctl -u nginx.service -b --no-pager -n 60
Dec 30 10:14:03 server systemd[1]: Starting nginx.service - A high performance web server and a reverse proxy server...
Dec 30 10:14:03 server nginx[21984]: nginx: [emerg] unexpected "}" in /etc/nginx/sites-enabled/app.conf:57
Dec 30 10:14:03 server systemd[1]: nginx.service: Control process exited, code=exited, status=1/FAILURE
Dec 30 10:14:03 server systemd[1]: nginx.service: Failed with result 'exit-code'.
Dec 30 10:14:03 server systemd[1]: Failed to start nginx.service - A high performance web server and a reverse proxy server.
Що це означає: Журнал підтверджує точну помилку парсера. Додаткові вгадки не потрібні.
Рішення: Відкрийте файл, виправте синтаксис, потім знову протестуйте конфіг перед перезапуском.
Завдання 3: Витягти логи «з моменту перезапуску», коли завантаження шумне
cr0x@server:~$ systemctl show -p ActiveEnterTimestampMonotonic nginx.service
ActiveEnterTimestampMonotonic=81234567890
cr0x@server:~$ journalctl -u nginx.service -b --no-pager --since "2 min ago"
Dec 30 10:14:03 server systemd[1]: Starting nginx.service - A high performance web server and a reverse proxy server...
Dec 30 10:14:03 server nginx[21984]: nginx: [emerg] unexpected "}" in /etc/nginx/sites-enabled/app.conf:57
Dec 30 10:14:03 server systemd[1]: nginx.service: Control process exited, code=exited, status=1/FAILURE
Dec 30 10:14:03 server systemd[1]: nginx.service: Failed with result 'exit-code'.
Що це означає: Ви звужуєте логи за часом, замість обробляти весь процес завантаження.
Рішення: Якщо помилки немає в цьому вікні, розширте до 10 хвилин; але не знімайте фільтр за юнітом поки що.
Завдання 4: Проінспектуйте юніт на предмет передстартових перевірок і файлів середовища
cr0x@server:~$ systemctl cat nginx.service
# /lib/systemd/system/nginx.service
[Unit]
Description=A high performance web server and a reverse proxy server
After=network-online.target
Wants=network-online.target
[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on;
ExecStart=/usr/sbin/nginx -g daemon on; master_process on;
ExecReload=/usr/sbin/nginx -g daemon on; master_process on; -s reload
TimeoutStopSec=5
KillMode=mixed
[Install]
WantedBy=multi-user.target
Що це означає: Невдача не в довгоживучому демонові; вона в кроці валідації. Також тут немає EnvironmentFile=, отже прихованих змінних менше.
Рішення: Запустіть точну передстартову команду вручну, щоб відтворити проблему; якщо вона падає — виправляйте конфіг. Якщо проходить — причина в оточенні (права, AppArmor, шляхи include).
Завдання 5: Запустіть тест конфігурації демона вручну (та сама команда)
cr0x@server:~$ sudo /usr/sbin/nginx -t -q -g "daemon on; master_process on;"
nginx: [emerg] unexpected "}" in /etc/nginx/sites-enabled/app.conf:57
Що це означає: Це детерміністична помилка парсингу конфігурації. Жодної містики systemd.
Рішення: Виправте згаданий файл і рядок. Не перезапускайте по колу в надії, що «все само відновиться». Не відновиться.
Завдання 6: Знайдіть проблемний рядок і перевірте структуру include
cr0x@server:~$ nl -ba /etc/nginx/sites-enabled/app.conf | sed -n '45,70p'
45 server {
46 listen 443 ssl;
47 server_name app.example.internal;
48 include /etc/nginx/snippets/tls.conf;
49
50 location / {
51 proxy_pass http://127.0.0.1:8080;
52 proxy_set_header Host $host;
53 }
54
55 } # end server
56
57 }
Що це означає: На рядку 57 зайва закриваюча дужка.
Рішення: Видаліть її, збережіть, знову запустіть тест конфігурації. Якщо у вас часто невідповідності дужок — введіть стиль: один блок на файл, узгоджене відступлення та лінтер конфігів у CI.
Завдання 7: Перевірте ще раз, потім перезапустіть (не пропускайте крок валідації)
cr0x@server:~$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Що це означає: Тепер безпечно перезапускати.
Рішення: Перезапустіть лише один раз. Якщо перезапуск і досі не вдається — це інша проблема, не припускайте, що це ще синтаксис конфігурації.
cr0x@server:~$ sudo systemctl restart nginx.service
cr0x@server:~$ systemctl is-active nginx.service
active
Що це означає: Служба запущена.
Рішення: Перевірте, що вона обслуговує трафік (локальна перевірка здоров’я) і коректно закрийте інцидент.
Завдання 8: Коли статус нічого не каже, покажіть повні логи з фільтром за пріоритетом
cr0x@server:~$ journalctl -u nginx.service -b -p warning --no-pager
Dec 30 10:14:03 server nginx[21984]: nginx: [emerg] unexpected "}" in /etc/nginx/sites-enabled/app.conf:57
Що це означає: Ви відфільтрували до warning і вище, тож не читаєте «Started…» шум.
Рішення: Використовуйте це, коли юніт дуже балакучий. Якщо на warning/error нічого немає, то логування йде в інше місце або відома тиша до ініціалізації логування.
Завдання 9: Підтвердьте, які файли конфігурації змінювалися недавно (зловіть реального винуватця)
cr0x@server:~$ sudo find /etc/nginx -type f -printf '%TY-%Tm-%Td %TH:%TM %p\n' | sort | tail -n 8
2025-12-30 10:12 /etc/nginx/sites-enabled/app.conf
2025-12-29 18:41 /etc/nginx/nginx.conf
2025-12-10 09:03 /etc/nginx/snippets/tls.conf
2025-11-21 15:22 /etc/nginx/mime.types
Що це означає: Ви можете корелювати відмову запуску з найсвіжішим редагуванням.
Рішення: Якщо помилка посилається на файл include, перевірте mtime і для нього. «Я змінив лише один рядок» рідко буває повною правдою.
Завдання 10: Якщо це не синтаксис, перевірте permission denied (класика після «загартування»)
cr0x@server:~$ journalctl -u nginx.service -b --no-pager -n 30
Dec 30 10:20:11 server nginx[22310]: nginx: [emerg] open() "/etc/nginx/snippets/tls.conf" failed (13: Permission denied)
Dec 30 10:20:11 server systemd[1]: nginx.service: Control process exited, code=exited, status=1/FAILURE
cr0x@server:~$ namei -l /etc/nginx/snippets/tls.conf
f: /etc/nginx/snippets/tls.conf
drwxr-xr-x root root /
drwxr-xr-x root root etc
drwxr-xr-x root root nginx
drwx------ root root snippets
-rw------- root root tls.conf
Що це означає: Права каталогу заважають nginx (який працює як www-data після старту) або його передстартовій перевірці прочитати включення.
Рішення: Виправте права до мінімально необхідних. Зазвичай: біт виконання для каталогів для проходження та читання файлу для користувача або групи служби.
Завдання 11: Підтвердьте користувача виконання і sandboxing служби
cr0x@server:~$ systemctl show nginx.service -p User -p Group -p DynamicUser -p ProtectSystem -p ReadWritePaths
User=
Group=
DynamicUser=no
ProtectSystem=no
ReadWritePaths=
Що це означає: Цей юніт не використовує директиви sandboxing systemd. Якщо ви бачите ProtectSystem=strict або жорсткі ReadWritePaths, читання/запис конфігів може бути заблоковане.
Рішення: Якщо sandboxing увімкнено, налаштуйте його під потреби демона, а не вимикайте сліпо. Додайте явні ReadOnlyPaths/ReadWritePaths в оверрайді.
Завдання 12: Інтерпретуйте причини відмови з перспективи systemd (коди виходу і сигнали)
cr0x@server:~$ systemctl show nginx.service -p ExecMainStatus -p ExecMainCode -p Result
ExecMainStatus=1
ExecMainCode=exited
Result=exit-code
Що це означає: Процес завершився нормально з кодом 1. Не SIGKILL, не OOM, не таймаут.
Рішення: Зосередьтеся на конфігурації, параметрах і правах. Якщо бачите ExecMainCode=killed або Result=timeout, це інша гілка діагностики.
Завдання 13: Якщо служба флапає, зупиніть цикл перезапусків, поки читаєте журнали
cr0x@server:~$ sudo systemctl reset-failed nginx.service
cr0x@server:~$ sudo systemctl stop nginx.service
cr0x@server:~$ systemctl status nginx.service --no-pager
● nginx.service - A high performance web server and a reverse proxy server
Loaded: loaded (/lib/systemd/system/nginx.service; enabled; preset: enabled)
Active: inactive (dead)
Що це означає: Ви не дозволяєте systemd безупинно перезапускати службу, поки налагоджуєте. Це також робить журнал читабельнішим.
Рішення: Робіть це, коли Restart=always створює шум і навантаження. Потім перезапустіть свідомо, коли матимете виправлення.
Завдання 14: Безпечно порівняйте зміни конфігурації з метаданими dpkg (перевірка пакування)
cr0x@server:~$ dpkg -S /etc/nginx/nginx.conf
nginx-common: /etc/nginx/nginx.conf
cr0x@server:~$ sudo ls -l /etc/nginx/nginx.conf*
-rw-r--r-- 1 root root 1492 Dec 29 18:41 /etc/nginx/nginx.conf
-rw-r--r-- 1 root root 1479 Nov 21 15:22 /etc/nginx/nginx.conf.dpkg-dist
Що це означає: Можливо, у вас є дистрибутивний новий файл за замовчуванням або невирішений мердж. Це може взаємодіяти з вашою зміною.
Рішення: Якщо служба почала падати після оновлення плюс редагування конфігу, перевірте .dpkg-dist/.dpkg-old і свідомо узгодьте.
Завдання 15: Коли журнали відсутні, підтвердіть збереження journald і обмеження швидкості
cr0x@server:~$ sudo grep -E '^(Storage|SystemMaxUse|RateLimitIntervalSec|RateLimitBurst)=' /etc/systemd/journald.conf | sed '/^#/d;/^$/d'
Storage=auto
RateLimitIntervalSec=30s
RateLimitBurst=1000
cr0x@server:~$ journalctl --disk-usage
Archived and active journals take up 384.0M in the file system.
Що це означає: Якщо Storage=volatile, ви втрачаєте журнали при перезавантаженні. Якщо обмеження швидкості низьке, ви можете пропустити повторювані помилки.
Рішення: Для продакшну зберігайте журнали на диску і налаштуйте розмір адекватно. Для налагодження тимчасово підніміть ліміти швидкості, якщо служба спамить, але потім виправте джерело спаму.
Жарт №2 (короткий, по темі): «Вчора працювало» — це не доказ; це свідчення свідка з жахливою пам’яттю.
Три корпоративні міні-історії (і чому вони повчають)
Міні-історія 1: Інцидент через неправильне припущення
Команда мала флот Debian-хостів з веб- і API-службами. Одного дня вийшла рутинна зміна конфігу: оновлення TLS-шифрів, уніфікація в середовищах. Хтось перезапустив nginx на канарці. Він впав. Вони запустили nginx -t вручну; тест пройшов. Припущення виникло миттєво: «systemd зламався на цьому хості».
Вони рилися у версіях пакетів, параметрах ядра, навіть SELinux (який взагалі не був увімкнений). Тим часом трафік стікав з вузла, автоскейлер нервував. Вони продовжували пробувати перезапуски «просто подивитися», що чудово стирає єдиний корисний рядок помилки купою нових перезапусків.
Виправлення було смішно простим: systemd-юніт використовував інший шлях конфігурації через файл середовища. Не навмисно — просто історично. Ручний nginx -t тестував /etc/nginx/nginx.conf; systemd тестував /etc/nginx/nginx-canary.conf. Файл канарки включав шлях, якого не було на цьому хості.
Урок не в тому, щоб «не використовувати environment files». Він у тому, щоб ніколи не припускати, що ваше ручне відтворення збігається з тим, що робить менеджер служб. Витягніть точні ExecStartPre/ExecStart з systemctl cat і запустіть цю команду. Якщо є файл середовища — виведіть його і припиніть гадати.
Міні-історія 2: Оптимізація, яка відгукнулась проти
Платформна група вирішила «прискорити деплои», замінивши restart на reload, коли можливо. Reload дешевший: менше розривів з’єднань, менше транзієнтних помилок. Добре складений намір. Потім вони застосували це масово скриптом.
Одна служба, брокер повідомлень, приймала сигнал reload, але застосовувала конфіг частково. Для деяких налаштувань потрібен був повний рестарт, але reload повертав успіх. З часом з’явився дрейф конфігів: запущений конфіг не відповідав тому, що на диску, і люди перестали довіряти обом.
Зрештою зміна конфігурації додала параметр, який упав би при чистому старті. Reload нічого не зробив, сказав «OK», і система працювала зі старими налаштуваннями. Через дні відбулося звичайне перезавантаження хоста. Тепер службі довелось робити cold start, вона прочитала поганий конфіг і відмовилася запускатися. Відмова сталася під час maintenance window — там, де зустрічаються ваші майбутні помилки.
Урок: reload не безкоштовний. Якщо ви обираєте reload як оптимізацію, також треба забезпечити валідацію конфігурації в процесі зміни та періодично робити контрольовані перезапуски, щоб довести, що конфіг фактично стартує.
Міні-історія 3: Нудна, але правильна практика, яка врятувала день
Внутрішня сервісна програма для фінансів працювала на Debian, підкріплена базою даних і веб-інтерфейсом. У них була політика змін, яка не була гламурною: кожна правка конфігу мала коміт у репо, а деплой-утиліти завжди запускали вбудований тест конфігу служби перед зміною systemd. Якщо тест падав, зміна просто не зігружалась.
Люди скаржилися: «це гальмує». «Я можу протестувати в голові». Звично. Але прийшов день, коли старший інженер редагував конфіг вживу під час інциденту — бо служба погано поводилась і потрібна була швидка міра. Правка мала тонку помилку у лапках. Наступний перезапуск убив би службу повністю.
Інструмент деплою відмовився застосувати зміну без проходження тесту конфігу. Оце і було сенс: запобіжні рамки, коли стрес робить всіх неакуратними. Вони виправили лапки, повторно протестували, потім безпечно перезапустили. Ніхто не отримав друге повідомлення від пейджера.
Урок: нудна практика — не репозиторій. Це автоматична валідація плюс передбачуваний шлях відкату. Ці дві речі не дають маленьким помилкам перерости в outage.
Поширені помилки: симптом → корінна причина → виправлення
Ось повторювані донори проблем. Якщо служба не запускається після зміни конфігурації, ви, ймовірно, потрапите в одну з цих категорій.
1) Симптом: systemctl status показує «failed (Result: exit-code)» без корисної помилки
Корінна причина: Ви бачите лише підсумок. Змістовний рядок розташований раніше або обрізаний.
Виправлення: Запитуйте журнал напряму і розширте фрагмент.
cr0x@server:~$ journalctl -u myservice.service -b --no-pager -n 200
...look for the first real error line...
2) Симптом: служба падає миттєво після перезапуску; логи згадують ExecStartPre
Корінна причина: Передстартова валідація не пройшла (синтаксис, відсутній include, недійсна директива).
Виправлення: Запустіть ту саму валідацію вручну і виправте конфіг перед перезапуском.
cr0x@server:~$ systemctl cat myservice.service | sed -n '/ExecStartPre/p'
ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on;
3) Симптом: тест конфігу проходить вручну, але падає під systemd
Корінна причина: Інший шлях до конфігу, інший користувач, інше оточення або обмеження sandbox.
Виправлення: Витягніть точну команду і оточення з юніта; запустіть від імені користувача служби.
cr0x@server:~$ systemctl show myservice.service -p Environment -p EnvironmentFiles
Environment=
EnvironmentFiles=/etc/default/myservice (ignore_errors=no)
4) Симптом: «Permission denied» на includes, сертифікатах, сокетах, PID-файлах
Корінна причина: Зміни в жорсткості прав (chmod/chown), новий шлях з обмеженими правами або невідповідність користувача служби.
Виправлення: Простежте права шляху з namei -l; виправте біт виконання каталогів і читання файлів.
5) Симптом: «Address already in use» після зміни конфігурації
Корінна причина: Ви змінили порт/прив’язку; інша служба вже займає його; або старий екземпляр не зупинився коректно.
Виправлення: Визначте, хто займає порт; вирішіть, чи змінити порт назад, зупинити конфліктну службу або налаштувати socket activation.
cr0x@server:~$ sudo ss -ltnp | grep ':443 '
LISTEN 0 511 0.0.0.0:443 0.0.0.0:* users:(("haproxy",pid=1203,fd=7))
6) Симптом: юніт показує Result=timeout
Корінна причина: Демон зависає під час старту (чекає DNS, сховища, міграцій) або таймаут systemd занадто жорсткий для холодного старту.
Виправлення: Читайте журнали навколо зависання, потім змінюйте TimeoutStartSec лише якщо стартова робота легітимна і обмежена в часі.
7) Симптом: після зміни конфігу служба «запускається», але не працює
Корінна причина: Ви використали reload і припустили, що це застосувало все; або конфіг прийнятий, але семантично неправильний.
Виправлення: Запустіть перевірку на рівні застосунку та підтвердіть активний конфіг через інструменти самоінспекції служби. Перезапустіть за потреби.
8) Симптом: журнал не має записів для юніта
Корінна причина: Служба логувала у файл (або stdout перенаправлено), journald — volatile, або юніт ніколи не виконався через проблему залежностей.
Виправлення: Перевірте systemctl list-dependencies і налаштування journald; інспектуйте файлові логи, якщо служба їх використовує.
Чек-листи / поетапний план (безпечні виправлення і відкат)
Крок за кроком: діагностика і виправлення без стресу системи
- Зупиніть цикл перезапусків, якщо є. Якщо юніт флапає, поставте паузу, щоб читати стабільні журнали.
- Прочитайте підсумок юніта. Визначте, чи впав
ExecStartPre, чи помер основний процес. - Запитуйте journald по юніту і boot. Не починайте з глобальних логів.
- Витягніть точні команди старту. Читайте
systemctl catі перевіряйте drop-in файли. - Запустіть тест конфігу служби вручну. Ті самі аргументи, той самий шлях конфігу.
- Виправте найменшу річ, яка дозволяє стартувати. Уникайте рефакторингу під час відповіді на інцидент.
- Перезапустіть один раз, потім перевірте на рівні застосунку. «active (running)» — це не те саме, що «обслуговує».
- Запишіть корінну помилку. Вставте точний рядок помилки в нотатку інциденту. Майбутній ви подякує сьогоднішньому вам.
План відкату: коли ви не впевнені, що виправлення правильне
Якщо ви не можете довести виправлення швидко — відкатуйте. Не «ітеруйте в продакшні», поки пейджер голосно співає.
- Збережіть зламаний конфіг. Скопіюйте його з часовою міткою для подальшого аналізу.
- Відновіть останній відомо-робочий з репо чи бекапу.
- Проведіть валідацію конфігу. Завжди запускайте тестовий режим демона.
- Перезапустіть службу і перевірте.
- Лише після відновлення: налагодьте зламану зміну в контрольованому середовищі.
cr0x@server:~$ sudo cp -a /etc/nginx/sites-enabled/app.conf /root/app.conf.broken.$(date +%F-%H%M%S)
cr0x@server:~$ sudo cp -a /root/rollback/app.conf /etc/nginx/sites-enabled/app.conf
cr0x@server:~$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
cr0x@server:~$ sudo systemctl restart nginx.service
cr0x@server:~$ systemctl is-active nginx.service
active
Коли потрібно тримати часткову службу в робочому стані (контроль збитків)
Іноді ви не можете повністю виправити негайно, але можете зменшити вплив:
- Відновіть мінімальний конфіг, який подає сторінку обслуговування.
- Вимкніть зламаний віртуальний хост, залишивши інші працюючими.
- Маршрутизувати трафік з вузла тимчасово, виправити в ізоляції, а потім повернути.
Не відключайте кроки валідації, щоб «змусити» службу стартувати, якщо ви не впевнені, що демон не запуститься в корупованому стані. Цей шлях веде до втрати даних, і вам не сподобається постмортем.
FAQ
1) Чому systemctl status недостатньо?
Тому що воно навмисно компактне. Воно показує невеликий хвіст журналу і підсумок стану юніта. Використовуйте його, щоб знайти назву юніта, фазу відмови, а потім переходьте до journalctl -u для реальної діагностики.
2) Яка найкраща команда journalctl для цієї ситуації?
Зазвичай:
cr0x@server:~$ journalctl -u myservice.service -b --no-pager -n 200
Якщо це шумить, додайте -p warning або обмежте час через --since.
3) Як зрозуміти, чи це проблема конфігурації чи runtime?
Шукайте, чи не впав ExecStartPre (конфіг/валідація) або чи основний процес спочатку стартував, а потім помер (runtime). systemctl status зазвичай каже, який процес впав.
4) Чому іноді запуск тесту конфігу вручну проходить, а під systemd — ні?
Інше оточення. systemd може використовувати файл середовища, інший робочий каталог, sandboxing або інший користувацький контекст. Завжди відтворюйте, використовуючи точну командну лінію з юніта.
5) Як побачити drop-in оверрайди, які можуть змінювати поведінку?
cr0x@server:~$ systemctl status myservice.service --no-pager
...look for "Drop-In:" lines...
cr0x@server:~$ systemctl cat myservice.service
...includes /etc/systemd/system/myservice.service.d/*.conf if present...
6) Коли варто використовувати reload замість restart?
Тільки коли служба документує, що reload застосовує зроблені зміни, і у вас є крок валідації. Якщо невпевнені — перезапустіть у безпечне вікно або після зливання трафіку.
7) Що робити, якщо для юніта взагалі немає журналів?
Тоді або юніт не виконався, journald не зберігає журнали, або логи йдуть в інше місце (наприклад, /var/log/*). Перевірте залежності і налаштування journald, огляньте файлові логи, якщо служба їх налаштовує.
8) Як швидко зрозуміти, чи це проблема з правами доступу?
Шукайте «Permission denied» у журналі, потім простежте шлях файлу через namei -l. Проблеми з правами часто виникають від відсутності бітів виконання каталогів або змін загартування, які забули про користувача служби.
9) Який найнадійніший спосіб запобігти цьому класу відмов?
Автоматизуйте валідацію конфігу (режим тесту демона) перед restart/reload, тримайте конфіги в контролі версій і зробіть відкат тривіальним. Мета — зловити зламаний рядок раніше, ніж його побачить systemd.
Висновок: подальші кроки, щоб уникнути повторних інцидентів
Служба Debian 13, що падає після зміни конфігурації, рідко є загадкою. Зазвичай це один точний рядок помилки, який ви не витягли чисто. Прочитайте юніт, щоб дізнатися, що виконувалося. Прочитайте журнал, звужений до юніта, щоб дізнатися, що впало. Потім вручну протестуйте конфіг, використовуючи ту саму команду, яку використовує systemd.
Практичні подальші кроки:
- Додайте переддеплойну перевірку конфігу для кожної служби, яка її підтримує.
- Навчіть команду ставитися до
systemctl statusяк до підказки, а не як до діагнозу. - Зробіть відкат першокласною операцією (копіювати, відновити, валідувати, перезапустити).
- Стандартизуйте короткий «швидкий план діагностики» і тримайте його поруч із ротацією пейджера.
Зробіть це — і наступного разу, коли служба відмовиться запускатися, ви витратите час на виправлення реальної проблеми, а не на сперечання з екраном підсумку.