Ubuntu 24.04 systemd unit overrides: виправляйте сервіси чисто, не редагуючи файли постачальника (випадок №8)

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

Ви змінили /lib/systemd/system/something.service о 2-й ночі, сервіс «працював», а потім оновлення пакета тихо скасувало вашу правку.
Тепер ви дивитеся на цикл перезапусків і не розумієте, які спогади вам брешуть.

Ubuntu 24.04 — це світ systemd. Правильний крок майже ніколи не полягає в «редагуванні файлa постачальника». Правильний крок — overrides: drop-in файли,
чисті, прозорі, відкатні. Ви отримуєте виправлення без крихкості — і перестаєте програвати боротьбу з dpkg.

Ментальна модель: що читає systemd і в якому порядку

systemd — це мерджер конфігурацій. Він не «завантажує один файл сервісу». Він будує остаточну конфігурацію юніта з кількох шарів, а потім запускає її.
Якщо ви ставитесь до нього як до одного файлу, вас постійно будуть дивувати наслідки.

Звідки беруться unit файли (Ubuntu 24.04)

На Ubuntu ви зазвичай побачите:

  • /lib/systemd/system/: файли юнітів від постачальника (встановлюються пакетами). Ви не володієте цими файлами.
  • /etc/systemd/system/: адмінські overrides та кастомні юніти. Ви володієте цим простором.
  • /run/systemd/system/: runtime юніти та транзієнтні drop-in. Ефемерні; живуть до перезавантаження.

Пріоритет фактично такий: /etc переважає /run, яке переважає /lib (є нюанси), плюс drop-in файли застосовуються в лексикальному порядку.
Правило великого пальця: якщо вам потрібно стабільне виправлення — покладіть його в /etc.

Drop-in: чистий скальпель

Канонічний механізм override — це drop-in файл:
/etc/systemd/system/<unit>.d/override.conf.
Він містить лише дельти, які вам потрібні, а не повну копію юніта. Це важливо, бо такий підхід читабельний, перевірюваний і стійкий до еволюції юніта від постачальника.

Ви також можете розміщувати кілька drop-in файлів (наприклад, 10-limits.conf, 20-env.conf). systemd завантажує їх в порядку.
Це значно полегшує відповідь на питання «хто що змінив», ніж «хтось редагував файл юніта на місці і тепер він став унікальною кастомною версією».

Різниця між редагуванням і override (і чому це важливо)

Редагування файлу постачальника — приваблива пастка. Це швидко і створює технічний борг одним натисканням клавіш.
В мить оновлення пакету dpkg:

  • перезапише юніт (якщо ви не позначили його як conf-файл), або
  • запитає в способах, які під час аварій часто «впорядковують» автоматично, або
  • залишить .dpkg-dist/.dpkg-old купу, яку ніхто не згадає

Overrides уникають усього цього. Пакет може робити що завгодно, але ваші наміри залишаються в силі.

Цитата, що триматиме вас чесними

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

Тримайте ваші зміни там, де ви їх бачите. Overrides саме для цього.

Вісім фактів і трохи історії (чому існують overrides)

  1. systemd дебютував у 2010 році (Lennart Poettering і Kay Sievers) і замінив зоопарк init-скриптів декларативними unit-файлами.
  2. Ubuntu перейшла на systemd за замовчуванням у 15.04; до 24.04 це вже не «новинка», а операційна парадигма для більшості пакувань сервісів.
  3. Drop-in створені для дистрибутивного пакування: постачальники дають безпечні значення; оператори додають політику для сайту без форку юніта.
  4. Шляхи пошуку unit-файлів — частина інтерфейсу; systemd навмисно збудований так, щоб мерджити конфіг з кількох місць, а не «читати один файл».
  5. systemctl edit — благословлений робочий потік; він створює директорії і відкриває редактор безпечно, включно з «сухими» змінами перед reload.
  6. Перекриття ExecStart= вимагає спочатку очищення; systemd трактує його як список, а не як одиночний рядок. Якщо забути reset-рядок, ви запустите два ExecStart (або жодного).
  7. Існує runtime-шар у /run; інструменти і генератори можуть створювати транзієнтні юніти, що корисно для логіки під час завантаження, але ускладнює відладку.
  8. systemd має потужну інспекцію: systemctl cat, systemd-analyze, journalctl -u і systemctl show дозволяють побачити, що насправді було вирішено.

Жарт №1: Редагувати /lib/systemd/system в проді — це як «просто тестувати в проді» — швидко, захопливо і лише іноді кар’єрно фатально.

Випадок №8: чистий override, що переживає оновлення

Ось ситуація, яку я постійно бачу на Ubuntu 24.04:
сервіс постачальника стартує нормально більшість днів, але під навантаженням досягає лімітів (файлові дескриптори, процеси, блокування пам’яті), або йому потрібна ще одна змінна середовища,
або робоча директорія неправильна, або йому треба чекати монтування. Спокуса — редагувати файл юніта там, де він лежить. Не робіть так.

Ваша мета: (1) ідентифікувати мінімальну зміну, (2) реалізувати її в /etc/systemd/system як drop-in, і
(3) довести, що systemd використовує злиту конфігурацію, яку ви задумали.

Типові патерни override, які «безпечні і нудні»

  • Ресурсні ліміти: LimitNOFILE=, TasksMax=, MemoryMax= — стабільно і без драм.
  • Порядок старта: After=, Requires=, Wants= — уникайте гонок з монтуваннями та мережею.
  • Середовище: Environment=, EnvironmentFile= — тримайте секрети поза юніт-файлом; використовуйте файли з правами доступу.
  • Поводження при рестарті: Restart=on-failure, RestartSec=, StartLimitIntervalSec= — налаштовуйте, але не приховуйте реальні помилки.
  • Зміни ExecStart: можливі, але потребують додаткової уваги та плану відкату.

Коли не варто робити override

Якщо сервіс поламаний через неправильний бінар, некоректний конфіг або відсутню залежність, override вас не врятує.
Overrides служать для зміни того, як systemd запускає коректну програму, а не для патчу самої програми.

Жарт №2: Якщо ви «виправили» segfault за допомогою Restart=always, вітаю — ви винайшли дуже швидкий генератор логів.

План швидкої діагностики: знайти вузьке місце швидко

Коли сервіс нездоровий, ви можете провести 30 хвилин, читаючи unit-файли… або 3 хвилини, подивившись у правильний вивід.
Ось порядок, який я використовую в проді.

1) Встановіть симптом: стан, код виходу та остання помилка

  • Перевірте статус: чи він failed, activating, чи працює, але деградований?
  • Перевірте код виходу: status=203/EXEC проти status=1/FAILURE проти OOM kill — це різні всесвіти.
  • Перегляньте останні рядки журналу: не гортаючи; попросіть journald про останні 50 рядків з часовими мітками.

2) Підтвердіть, що systemd насправді запускає

  • Виведіть злитий юніт: systemctl cat показує постачальника + drop-in.
  • Перевірте властивості: systemctl show -p ExecStart,Environment,LimitNOFILE щоб підтвердити ефективні значення.
  • Перевірте, чи генератор створив щось у /run: якщо так, ваші постійні зміни можуть бути перебиті або доповнені.

3) І тільки тоді редагуйте: мінімальна зміна, передбачуваний відкат

  • Створіть drop-in за допомогою systemctl edit.
  • Запустіть systemd-analyze verify, якщо ви змінили синтаксично складні частини.
  • daemon-reload, потім рестарт і перевірка.

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

Нижче — реальні завдання, які ви можете виконати на Ubuntu 24.04. Кожне містить, що означає вивід і яке рішення приймати далі.
Я використаю nginx.service як приклад, бо він поширений, але робочий процес ідентичний для баз даних, агентів, експортерів та кастомних демонів.

Завдання 1: Знайти, де лежить unit файл

cr0x@server:~$ systemctl show -p FragmentPath -p DropInPaths nginx.service
FragmentPath=/lib/systemd/system/nginx.service
DropInPaths=/etc/systemd/system/nginx.service.d/override.conf

Значення: FragmentPath — основний файл юніта, який використовує systemd. DropInPaths перераховує застосовані overrides.

Рішення: Якщо ваша зміна в /lib, ви тримаєте гранату. Перенесіть її в drop-in під /etc.

Завдання 2: Читайте злитий юніт, а не тільки фрагмент постачальника

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.target

[Service]
Type=forking
ExecStart=/usr/sbin/nginx -g 'daemon on; master_process on;'
ExecReload=/usr/sbin/nginx -g 'daemon on; master_process on;' -s reload
ExecStop=/sbin/start-stop-daemon --quiet --stop --retry QUIT/5 --pidfile /run/nginx.pid
PIDFile=/run/nginx.pid

# /etc/systemd/system/nginx.service.d/override.conf
[Service]
LimitNOFILE=65536

Значення: Це те, що systemd застосує. Це істина. Усе інше — коментарі.

Рішення: Якщо в злитому юніті немає вашої зміни — ви редагували не там або забули daemon-reload.

Завдання 3: Перевірте живий стан і останню причину виходу

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)
    Drop-In: /etc/systemd/system/nginx.service.d
             └─override.conf
     Active: failed (Result: exit-code) since Mon 2025-12-30 10:12:07 UTC; 15s ago
       Docs: man:nginx(8)
    Process: 2197 ExecStart=/usr/sbin/nginx -g daemon on; master_process on; (code=exited, status=1/FAILURE)
        CPU: 45ms

Значення: status=1/FAILURE вказує, що nginx виконався і повернув помилку (часто помилка конфігурації), а не проблема з exec.

Рішення: Йдіть у логи далі; не переписуйте ExecStart, поки не впевнені, що це потрібно.

Завдання 4: Витягніть недавні логи для юніта з часовими мітками

cr0x@server:~$ journalctl -u nginx.service -n 50 --no-pager -o short-iso
2025-12-30T10:12:07+00:00 server nginx[2197]: nginx: [emerg] invalid number of arguments in "worker_connections" directive in /etc/nginx/nginx.conf:12
2025-12-30T10:12:07+00:00 server systemd[1]: nginx.service: Main process exited, code=exited, status=1/FAILURE
2025-12-30T10:12:07+00:00 server systemd[1]: nginx.service: Failed with result 'exit-code'.

Значення: Сервіс впав через конфіг програми. Сьогодні problem systemd — не причина.

Рішення: Виправте конфіг nginx. Overrides вам не допоможуть. Якщо ваша зміна мала виправити шлях конфігу — перевірте цю гіпотезу.

Завдання 5: Підтвердіть, чи існує drop-in і що в ньому

cr0x@server:~$ systemctl edit nginx.service --full
# (editor opens the full unit)

Значення: --full створює повну копію юніта в /etc/systemd/system. Це важкий молоток.

Рішення: Віддавайте перевагу systemctl edit nginx.service (drop-in). Використовуйте --full лише якщо треба повністю замінити юніт.

Завдання 6: Створіть правильний drop-in override (рекомендовано)

cr0x@server:~$ systemctl edit nginx.service
# (editor opens /etc/systemd/system/nginx.service.d/override.conf)

Додайте щось на кшталт:

cr0x@server:~$ sudo cat /etc/systemd/system/nginx.service.d/override.conf
[Service]
LimitNOFILE=65536
TasksMax=4096

Значення: Ви не форкуєте юніт. Ви наносите політику шаром зверху.

Рішення: Тримайте overrides маленькими. Якщо ваш override.conf довший за файл постачальника — ви пишете власний юніт — візьміть його на повне обслуговування.

Завдання 7: Перезавантажте systemd після зміни файлів юніта

cr0x@server:~$ sudo systemctl daemon-reload

Значення: systemd перечитує визначення юнітів. Без цього він може тримати старі версії.

Рішення: Якщо зміни «не застосовуються», спочатку підозрівайте, що ви забули reload. Друга підозра: ви редагували файл, яким systemd не користується.

Завдання 8: Перевірте ефективні значення, які systemd буде застосовувати

cr0x@server:~$ systemctl show nginx.service -p LimitNOFILE -p TasksMax -p Environment
LimitNOFILE=65536
TasksMax=4096
Environment=

Значення: Це ефективна конфігурація після мерджу всіх фрагментів і drop-in файлів.

Рішення: Якщо ви очікували певне значення, а його тут немає — знайдіть, що вас перебиває (порядок drop-in, повний юніт в /etc або транзієнтний юніт).

Завдання 9: Правильно перевизначте ExecStart (спочатку очистіть)

Ось що люди роблять неправильно. У systemd багато директив — типу списку. ExecStart= — одна з них.
Щоб замінити його, треба спочатку очистити існуючий список.

cr0x@server:~$ sudo cat /etc/systemd/system/nginx.service.d/10-execstart.conf
[Service]
ExecStart=
ExecStart=/usr/sbin/nginx -g 'daemon on; master_process on;' -c /etc/nginx/nginx.conf

Значення: Порожній рядок ExecStart= скидає список; наступний рядок стає єдиним ExecStart.

Рішення: Якщо ви не скинули, ви можете отримати кілька ExecStart рядків. Кращий випадок: старт провалиться. Найгірший: буде «працювати», поки не перестане.

Завдання 10: Виявити «шторм рестартів» і зупинити його безпечно

cr0x@server:~$ systemctl show nginx.service -p NRestarts -p Restart -p RestartUSec
NRestarts=27
Restart=on-failure
RestartUSec=100ms

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

Рішення: Тимчасово зупиніть і замаскуйте (mask) під час відладки (якщо безпечно), або збільште RestartSec= через drop-in, щоб сповільнити цикл.

Завдання 11: Перевірте, чи не боретеся ви з повною заміною юніта в /etc

cr0x@server:~$ systemctl show nginx.service -p FragmentPath
FragmentPath=/etc/systemd/system/nginx.service

Значення: Хтось створив повний юніт в /etc, що повністю переважає файл постачальника.

Рішення: Якщо ви не хотіли володіти цілим юнітом, видаліть повний юніт і замініть його drop-in файлами. Це поширений наслідок «ми колись використали –full».

Завдання 12: Визначте проблеми з порядком/залежностями (монтування, мережа тощо)

cr0x@server:~$ systemctl list-dependencies --reverse nginx.service
nginx.service
● multi-user.target

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

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

Завдання 13: Перевірте синтаксис юніта перед рестартом критичних сервісів

cr0x@server:~$ systemd-analyze verify /etc/systemd/system/nginx.service.d/10-execstart.conf

Значення: Зазвичай відсутність виводу означає «помилок не знайдено». Якщо є синтаксична помилка — ви побачите її до того, як вперетеся в production.

Рішення: Використовуйте verify, коли торкаєтеся складних директив (ExecStart, залежності, sandboxing). Це дешевше за шторм у pager.

Завдання 14: Чисто відкотити overrides

cr0x@server:~$ sudo systemctl revert nginx.service
Removed "/etc/systemd/system/nginx.service.d/override.conf".
Removed "/etc/systemd/system/nginx.service.d/10-execstart.conf".

Значення: revert видаляє drop-in файли і повертає юніт до стану постачальника (або до того, що залишилося).

Рішення: Використовуйте це, коли ваш override погіршив ситуацію і вам потрібна швидка кнопка «повернутися до відомої базової конфігурації».

Завдання 15: Підтвердіть, які overrides застосовано зараз (з порядком файлів)

cr0x@server:~$ systemctl show nginx.service -p DropInPaths
DropInPaths=/etc/systemd/system/nginx.service.d/10-execstart.conf /etc/systemd/system/nginx.service.d/override.conf

Значення: Порядок має значення. Лексикальний порядок має значення. Ваш файл 90-* переб’є 10-*.

Рішення: Якщо ви нанизуєте кілька змін, називайте файли свідомо. Не дозволяйте «override.conf» стати загальною шухлядою.

Завдання 16: Доведіть, що виконуваний процес отримав задані ліміти

cr0x@server:~$ systemctl show nginx.service -p MainPID
MainPID=2418
cr0x@server:~$ cat /proc/2418/limits | head -n 8
Limit                     Soft Limit           Hard Limit           Units
Max cpu time              unlimited            unlimited            seconds
Max file size             unlimited            unlimited            bytes
Max data size             unlimited            unlimited            bytes
Max stack size            8388608              unlimited            bytes
Max core file size        0                    unlimited            bytes
Max resident set          unlimited            unlimited            bytes
Max processes             4096                 4096                 processes

Значення: Це показує, що ядро фактично накладає на процес.

Рішення: Якщо значення в /proc не співпадають, у вас може бути кілька процесів (master/worker), або сервіс форкається і ліміти застосовуються по-іншому. Перевірте правильний PID.

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

Міні-історія 1: Інцидент через хибне припущення

Середня SaaS компанія мала флот Ubuntu серверів, що запускали пересилювач логів як systemd сервіс.
Після рутинного оновлення безпеки форвардер почав падати. Інженери побачили, що сервіс використовував
unit-файл у /lib/systemd/system і припустили: «це стабільно, мало що зміниться».

Місяць тому хтось «тимчасово» відредагував файл постачальника, щоб додати змінну середовища:
Environment=HTTP_PROXY=.... Це було недокументовано, без рев’ю і невидимо для CM, бо не було в /etc.
Оновлення безпеки замінило пакет, і проксі зник. Форвардер не зміг дістатися колектора, і логи перестали текти.

Тривога, що спрацювала, не була «форвардер впав». Це було низхідне: панелька мовчала,
потім джоб експорту відповідності провалився, бо очікував логи. Люди годину ганялися за неправильною системою.
Першою підказкою були повідомлення в journald: повторювані помилки підключення після часу оновлення пакета.

Виправлення було нудним: drop-in в /etc/systemd/system для встановлення проксі, плюс запис у runbook.
Постмортем рекомендував: ніколи не змінювати файли постачальника напряму і додати перевірку аудиту unit-файлів у виявлення дрейфу конфігурації.

Міні-історія 2: Оптимізація, що відбилася

Інша компанія запустила latency-sensitive сервіс з агресивними налаштуваннями рестарту.
Хтось помітив, що після збою час відновлення занадто повільний.
Вони зменшили RestartSec до 100ms і підняли StartLimitBurst, «щоб тримати доступність».

Це справді зменшило час між збоями і рестартами. І це була проблема.
Латентний баг конфігу почав викликати періодичні збої. Замість одного чистого крашу і стабільного рестарту
сервіс увійшов у швидкий цикл падінь. CPU злетів, логи вибухнули, і інші сервіси на хості почали пропускати дедлайни через I/O навантаження.

Далі — відмова: rate limiting journald. Самі логи, потрібні для діагностики первинної помилки, стали неповними. Тим часом моніторинг бачив «сервіс працює» періодично і не повідомив одразу.
Усі втратили час, бо симптоми розмазалися по всьому хосту.

Відновлення було таким: зупинити юніт, відкотити override, потім повернути розумні значення:
Restart=on-failure, RestartSec=2s і помірний start limit.
Справжня оптимізація — змінити health check, щоб виявляти «швидкі рестарти» як відмову і швидше сповіщати.

Міні-історія 3: Нудна, але правильна практика, що врятувала день

Великий ентерпрайз мав політику: всі зміни systemd мають бути drop-in, названі з префіксом і номером тикету,
і кожен override має бути видимий в одному інвентарному звіті, знятому за допомогою systemctl show на кожному хості.
Це звучало як бюрократія, доки одного дня не стало рятівною практикою.

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

Натомість інженер on-call витягнув інвентарний звіт і одразу побачив, які сервери мали override, що торкався доступу до файлової системи (наприклад, ReadWritePaths), а які — ні.
Конвенція іменування зробила це пошуковим. Вони розгорнули одно-рядковий drop-in для вирівнювання поведінки, безпечно перезапустили агента і рухнули далі.

Практика не завадила зміні від постачальника. Вона запобігла плутанині. У проді ясність — це функція.

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

1) «Мій override не застосовується»

Симптом: Ви редагували drop-in, перезапустили сервіс і нічого не змінилося.

Корінь проблеми: Забули systemctl daemon-reload, або редагували файл у неправильному шляху, або повний юніт в /etc перебиває постачальника + drop-in.

Виправлення: Запустіть systemctl show -p FragmentPath -p DropInPaths unit; потім daemon-reload; потім systemctl cat unit щоб підтвердити злиту конфігурацію.

2) «Я перевизначив ExecStart і тепер він не стартує»

Симптом: Сервіс падає з дивними повідомленнями або намагається виконати кілька команд.

Корінь проблеми: Ви додали ExecStart=... без очищення існуючого списку.

Виправлення: У вашому drop-in: додайте порожній рядок ExecStart= перед новим ExecStart=.... Перезавантажте і рестартніть.

3) «Оновлення пакета скасувало моє виправлення»

Симптом: Поведінка сервісу змінилася відразу після apt upgrade.

Корінь проблеми: Ви редагували /lib/systemd/system/*.service напряму (територія постачальника).

Виправлення: Нанесіть зміну як drop-in під /etc/systemd/system/<unit>.d/. Розгляньте systemctl revert, щоб очистити випадкові повні копії юнітів.

4) «Запускається вручну, але не через systemd»

Симптом: Запуск бінарі у шеллі працює; systemd start провалюється.

Корінь проблеми: Відсутні змінні середовища, інша робоча директорія або суворіший sandboxing в контексті systemd.

Виправлення: Порівняйте systemctl show -p Environment -p WorkingDirectory; додайте EnvironmentFile= або WorkingDirectory= у drop-in; перевірте логи.

5) «Сервіс флапає й тягне за собою весь хост»

Симптом: Високе завантаження CPU, масові логи, «сервіс постійно перезапускається».

Корінь проблеми: Надто агресивна політика рестарту (Restart=always, крихітний RestartSec), або реальний crash-loop, загорнутий авто-рестартом.

Виправлення: Сповільніть: Restart=on-failure, RestartSec=2s. Зупиніть юніт, зніміть логи, виправте корінь проблеми, потім перезапустіть.

6) «Мій override поламався після додавання кількох drop-in»

Симптом: Налаштування «неначе» випадково змінюються в залежності від хоста.

Корінь проблеми: Порядок файлів drop-in відрізняється або ще один файл згодом перебиває ту саму директиву.

Виправлення: Використовуйте явну нумерацію (10-, 20-, 90-). Перевірте DropInPaths. Консолідуйте конфліктні директиви.

7) «Не бачить змонтовану директорію під час завантаження»

Симптом: Сервіс падає при завантаженні, але працює після ручного перезапуску.

Корінь проблеми: Відсутні ordering-залежності на mount unit; сервіс стартує раніше, ніж готова файлова система.

Виправлення: Додайте drop-in з RequiresMountsFor=/path або відповідні After=/Requires=. Перезавантажте daemon і перевірте поведінку після ребута.

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

Чеклист A: Зробити безпечний override (типовий підхід)

  1. Отримайте поточну істину: systemctl cat unit і systemctl show -p FragmentPath -p DropInPaths unit.
  2. Визначте найменшу можливу зміну (ліміти, env, порядок, політика рестарту).
  3. Створіть drop-in: sudo systemctl edit unit.
  4. Додайте лише потрібні директиви. Уникайте копіювання файлу постачальника.
  5. Валідуйте синтаксис, якщо торкалися складних частин: systemd-analyze verify ....
  6. sudo systemctl daemon-reload.
  7. Рестарт і верифікація: sudo systemctl restart unit потім systemctl status unit.
  8. Доведіть ефективну конфіг: systemctl show -p ... unit.
  9. Доведіть вплив у runtime (ліміти/env) через /proc або специфічні для сервісу діагностики.

Чеклист B: Ви мусите замінити ExecStart (високий ризик)

  1. Зніміть поточний ExecStart: systemctl show -p ExecStart unit.
  2. Створіть присвячений drop-in файл (не ховайте його): /etc/systemd/system/unit.d/10-execstart.conf.
  3. Спочатку скиньте список: додайте порожній рядок ExecStart=.
  4. Додайте потрібні ExecStartPre=, WorkingDirectory= та файли env.
  5. Перевірте: systemd-analyze verify.
  6. Перезавантажте daemon і рестартуйте.
  7. Майте готовий відкат: systemctl revert unit (або видаліть drop-in) і рестарт.

Чеклист C: Відкат і повернення до бази

  1. Зупиніть сервіс, якщо він флапає: sudo systemctl stop unit.
  2. Зробіть сніпшот поточного злитого юніта: systemctl cat unit у нотатки інциденту.
  3. Відкотіть overrides: sudo systemctl revert unit.
  4. Перезавантажте: sudo systemctl daemon-reload.
  5. Запустіть: sudo systemctl start unit.
  6. Підтвердіть логи: journalctl -u unit -n 50.

FAQ

1) Чи варто іноді редагувати файли в /lib/systemd/system?

Ні, не як практика. Ставтеся до них як до прошивки від постачальника: читаються, але не редагуються. Використовуйте drop-in у /etc/systemd/system.
Якщо треба експериментувати — робіть це на одноразовій ноді і перекладіть результат в override.

2) У чому різниця між systemctl edit і ручним редагуванням файлу?

systemctl edit створює правильну структуру директорій, відкриває потрібний файл і вирівнює з моделлю systemd.
Ручні правки ок якщо ви знаєте шляхи, але systemctl edit зменшує помилки «не в тому місці».

3) Чому мій override ExecStart= не замінив старий?

Тому що ExecStart — тип списку. Додайте порожній рядок ExecStart=, щоб очистити список, а потім додайте новий ExecStart=....

4) Як побачити фінальний юніт, який використовує systemd?

Використовуйте systemctl cat unit для злитої конфігурації і systemctl show -p FragmentPath -p DropInPaths unit щоб побачити джерела і застосовані drop-in.

5) Чи потрібно робити daemon-reload щоразу?

Якщо ви змінили файли юніта або drop-in — так. Перезапуск сервісу не гарантує повторного зчитування визначення юніта.
daemon-reload недорогий; простої не дешевші.

6) Який найчистіший спосіб видалити override?

sudo systemctl revert unit. Це видаляє drop-in і повертає до значень постачальника. Потім запустіть daemon-reload.

7) Чи можна через drop-in змінювати залежності, наприклад After= і Requires=?

Так, і це одне з найкращих застосувань. Якщо сервіс залежить від монту, розгляньте RequiresMountsFor=/path.
Для мережевих залежностей будьте обережні: «мережа піднята» не означає «віддалена залежність доступна».

8) Мій override працює на одному сервері, але не на іншому. Чому?

Найпоширеніші причини: інший drop-in перебиває його пізніше; повний юніт в /etc на одній ноді; або генератор створив щось у /run.
Порівняйте systemctl show -p FragmentPath -p DropInPaths між хостами.

9) Чи краще покласти все в один override.conf?

Не завжди. Один файл простий, доки не перетвориться на шухляду. Для більших змін розділяйте drop-in за призначенням з нумерацією:
10-limits.conf, 20-env.conf, 90-hardening.conf. Порядок стає явним.

10) Як підтвердити, що мої зміни лімітів дійсно застосовані до процесу?

Отримайте PID через systemctl show -p MainPID і перевірте /proc/<pid>/limits. Це те, що накладає ядро.

Висновок: наступні кроки, які можна зробити сьогодні

На Ubuntu 24.04 systemd overrides — це дорослий спосіб виправляти сервіси. Вони переживають оновлення, тримають ваші наміри окремо від значень постачальника
і пришвидшують реакцію на інциденти, бо питання «що змінилося» відповідається за секунди.

Практичні наступні кроки:

  • Виберіть один сервіс, який ви раніше «підправляли». Запустіть systemctl show -p FragmentPath -p DropInPaths і перевірте, чи є правки в /lib.
  • Якщо є — мігруйте їх в drop-in під /etc/systemd/system/<unit>.d/.
  • Уніфікуйте іменування drop-in (нумерація, призначення). Ваше майбутнє «я» — інша людина з іншим сном.
  • Навчіть команду двом командам: systemctl cat і systemctl revert. Одна знаходить правду; інша дає кнопку відкату.

Зробіть це кілька разів — і ви перестанете трактувати systemd як чорний ящик. Це не магія. Він просто дуже ретельно ставиться до того, куди ви кладете свої правки.

← Попередня
VPN між офісами: з’єднати два офіси в одну мережу (простий план, що працює)
Наступна →
DNS: зона BIND9 не завантажується — типові синтаксичні помилки й швидкі виправлення

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