Як використовувати systemd для запуску служби Linux при завантаженні
Забезпечення автоматичного запуску критичних служб при перезавантаженні сервера є однією з найбільш фундаментальних відповідальностей будь-якого адміністратора систем Linux. Незалежно від того, чи ви запускаєте веб-додаток, механізм бази даних або користувацький демон на середовищі VPS Hosting, несподіване перезавантаження ніколи не повинно означати тривале простоювання. За допомогою systemd — сучасної системи ініціалізації, яка живить більшість сучасних дистрибутивів Linux — ви можете точно визначити, як, коли та від кого запускаються ваші служби, все через чистий декларативний файл модуля.
Цей комплексний посібник проведе вас через кожен крок: розуміння того, що таке systemd, створення готового до виробництва файлу модуля служби, перевірка дозволів, тестування вашого виконуваного файлу та управління життєвим циклом служби. Наприкінці ваш користувацький додаток буде автоматично пережити кожне перезавантаження.
Що таке systemd і чому це важливо?
systemd — це система ініціалізації та менеджер служб, який замінив старіші альтернативи, такі як SysVinit та Upstart, у більшості основних дистрибутивів Linux, включаючи Ubuntu, Debian, CentOS, Rocky Linux, AlmaLinux та Fedora. Замість виконання послідовного ланцюга shell-скриптів під час завантаження, systemd паралелізує запуск служб, розв’язує впорядкування залежностей та управляє всім життєвим циклом системних процесів з єдиного уніфікованого інтерфейсу.
Ключові переваги systemd для серверних середовищ
| Функція | Переваги |
|---|---|
| Паралельний запуск служб | Швидше завантаження на серверах з кількома службами |
| Управління залежностями | Служби запускаються лише після того, як їх передумови готові |
| Політики автоматичного перезапуску | Упалі служби відновлюються без ручного втручання |
| Централізоване логування через journald | Весь вихід служби захоплюється в запитуваному журналі |
| Контроль ресурсів на основі cgroup | Обмеження CPU та пам’яті застосовуються для кожної служби |
| Активація сокету та пристрою | Служби запускаються за запитом, а не безумовно |
Для всіх, хто керує додатками на Dedicated Servers або екземплярах VPS, ці можливості безпосередньо перекладаються на вищу доступність та більш передбачувану поведінку під навантаженням.
Розуміння файлів модулів systemd
Все, що керує systemd, представлено файлом модуля — простим текстовим файлом конфігурації, розділеним на розділи. Файл модуля service повідомляє systemd:
- Що таке служба (метаданні, опис, залежності)
- Як її запустити (шлях до виконуваного файлу, робочий каталог, контекст користувача)
- Коли її запустити (цільова завантаження, впорядкування відносно інших модулів)
- Що робити, якщо вона не вдалася (політика перезапуску, затримка перезапуску)
Файли модулів служб для системних служб знаходяться в /etc/systemd/system/. Файли, розміщені тут, мають пріоритет над постачальниками одиниць у /lib/systemd/system/ та зберігаються при оновленнях пакетів.
Крок за кроком: створення модуля служби systemd
Наступний посібник використовує вигадану програму під назвою myapp. Замініть кожен екземпляр myapp, myuser та /usr/bin/myapp значеннями, відповідними вашому власному середовищу.
Крок 1: підготовка робочого каталогу
Перед написанням файлу модуля вирішіть, звідки буде запускатися ваша програма. Виділений робочий каталог зберігає файли конфігурації, журнали та дані часу виконання організованими та спрощує управління дозволами.
Створіть каталог, якщо він ще не існує:
sudo mkdir -p /opt/myapp> Чому /opt/ замість /etc/systemd/?
> Дерево /etc/systemd/ зарезервовано для власної конфігурації systemd. Розміщення даних програми там нестандартне і може викликати плутанину. Використовуйте /opt/myapp, /srv/myapp або /var/lib/myapp залежно від категорії стандарту ієрархії файлової системи, яка найкраще відповідає вашому навантаженню.
Призначте власність користувачу, який буде запускати службу:
sudo useradd --system --no-create-home --shell /usr/sbin/nologin myuser
sudo chown -R myuser:myuser /opt/myappВикористання виділеного системного облікового запису (без оболонки входу, без домашнього каталогу) є найкращою практикою безпеки. Це обмежує радіус вибуху, якщо програма коли-небудь буде скомпрометована.
Перевірте результат:
ls -ld /opt/myapp
# Expected output: drwxr-xr-x 2 myuser myuser 4096 Jan 1 00:00 /opt/myappКрок 2: створення файлу модуля служби
Відкрийте новий файл модуля за допомогою вашого улюбленого редактора:
sudo nano /etc/systemd/system/myapp.serviceВставте наступний вміст, коригуючи значення відповідно до вашої програми:
[Unit]
Description=My Custom Application
Documentation=https://example.com/docs
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
ExecStart=/usr/bin/myapp --config /opt/myapp/myapp.conf
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
RestartSec=5s
User=myuser
Group=myuser
WorkingDirectory=/opt/myapp
StandardOutput=journal
StandardError=journal
SyslogIdentifier=myapp
# Security hardening
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
[Install]
WantedBy=multi-user.targetЗбережіть файл за допомогою Ctrl+O, потім вийдіть за допомогою Ctrl+X.
Крок 3: розуміння кожної директиви
Розділ [Unit]
| Директива | Мета |
|---|---|
Description | Зрозуміла людиною назва, показана у виході systemctl status |
Documentation | Посилання на URL або сторінку посібника для служби |
After | Забезпечує запуск служби *після* активації зазначеної одиниці |
Wants | М’яка залежність — systemd *спробує* запустити зазначену одиницю, але не вийде, якщо вона недоступна |
> network-online.target проти network.target: Використовуйте network-online.target (у поєднанні з Wants=network-online.target) для служб, які справді потребують повністю налаштованого мережевого інтерфейсу — наприклад, програми, яка підключається до віддаленої бази даних або зовнішнього API під час запуску. network.target гарантує лише те, що підсистема мережі була *запущена*, а не те, що інтерфейси активні та адреси призначені.
Розділ [Service]
| Директива | Мета |
|---|---|
Type=simple | Процес, запущений ExecStart, є основним процесом (за замовчуванням для більшості програм) |
ExecStart | Повний шлях до двійкового файлу та будь-які аргументи. Завжди використовуйте абсолютні шляхи. |
ExecReload | Команда для перезавантаження конфігурації без повного перезапуску (необов’язково, але рекомендується) |
Restart=on-failure | Перезапустіть службу лише коли вона виходить з кодом, відмінним від нуля, або вбивається сигналом. Використовуйте always, якщо ви хочете перезапусків навіть при чистих виходах. |
RestartSec | Секунди очікування перед спробою перезапуску |
User / Group | Запустіть процес як цей користувач/група замість root |
WorkingDirectory | Встановіть поточний каталог перед виконанням ExecStart |
StandardOutput / StandardError | Маршрутизуйте stdout/stderr до журналу systemd |
SyslogIdentifier | Тег, використовуваний для фільтрування записів журналу для цієї служби |
NoNewPrivileges | Запобігає процесу отримання додаткових привілеїв через двійкові файли setuid |
ProtectSystem=strict | Монтує /usr, /boot та /etc як лише для читання для служби |
ProtectHome | Робить /home, /root та /run/user недоступними |
PrivateTmp | Надає службі власний приватний простір імен /tmp |
Розділ [Install]
| Директива | Мета |
|---|---|
WantedBy=multi-user.target | Включає службу, коли система досягає стандартного багатокористувацького (негафічного) рівня запуску. Це правильна ціль для практично всіх демонів сервера. |
Крок 4: перевірка дозволів файлу та каталогу
Перед перезавантаженням systemd переконайтеся, що користувач служби насправді може отримати доступ до всього, що йому потрібно:
# Check working directory ownership and permissions
ls -ld /opt/myapp
# Confirm the executable exists and is executable
ls -l /usr/bin/myapp
# Verify the config file is readable by myuser
sudo -u myuser cat /opt/myapp/myapp.confЯкщо будь-яка з цих перевірок не вдалася, виправте дозволи перед продовженням:
# Make the binary executable
sudo chmod +x /usr/bin/myapp
# Grant read access to the config file
sudo chmod 640 /opt/myapp/myapp.conf
sudo chown myuser:myuser /opt/myapp/myapp.confКрок 5: тестування виконуваного файлу вручну
Завжди перевіряйте, що ваша програма запускається правильно *перед* передачею контролю systemd. Це ізолює помилки програми від проблем конфігурації systemd:
sudo -u myuser /usr/bin/myapp --config /opt/myapp/myapp.confЯкщо програма запускається без помилок, натисніть Ctrl+C щоб зупинити її та продовжити. Якщо вона не вдалася, усуньте саму програму — перевірте, що всі залежності встановлені, змінні середовища встановлені та необхідні порти доступні.
Крок 6: перезавантаження systemd та включення служби
Після збереження файлу модуля наказати systemd повторно прочитати його конфігурацію:
sudo systemctl daemon-reloadВключіть службу, щоб вона запускалася автоматично при кожному наступному завантаженні:
sudo systemctl enable myapp.serviceЦя команда створює символічне посилання у відповідному каталозі .wants, пов’язуючи ваш файл модуля з послідовністю завантаження multi-user.target. Ви повинні побачити вихід, подібний до:
Created symlink /etc/systemd/system/multi-user.target.wants/myapp.service → /etc/systemd/system/myapp.service.Запустіть службу негайно без перезавантаження:
sudo systemctl start myapp.serviceКрок 7: перевірка того, що служба запущена
Перевірте поточний стан служби:
sudo systemctl status myapp.serviceЗдорова служба виробляє вихід, подібний до цього:
● myapp.service - My Custom Application
Loaded: loaded (/etc/systemd/system/myapp.service; enabled; vendor preset: disabled)
Active: active (running) since Wed 2025-01-01 12:00:00 UTC; 5s ago
Main PID: 12345 (myapp)
Tasks: 4 (limit: 4915)
Memory: 12.3M
CPU: 45ms
CGroup: /system.slice/myapp.service
└─12345 /usr/bin/myapp --config /opt/myapp/myapp.confКлючові поля для перевірки:
Loaded— підтверджує, що файл модуля був успішно проаналізований, і показує, чи є вінenabledабоdisabledдля завантаженняActive: active (running)— служба наразі запущенаMain PID— ідентифікатор процесу вашої програми
Крок 8: моніторинг журналів за допомогою journalctl
systemd маршрутизує весь вихід служби до журналу, структурованого, запитуваного сховища журналів. Використовуйте journalctl для перевірки:
# View all logs for myapp (most recent last)
journalctl -u myapp.service
# Follow live log output (like tail -f)
journalctl -u myapp.service -f
# Show only logs since the last boot
journalctl -u myapp.service -b
# Show the last 50 lines
journalctl -u myapp.service -n 50
# Show logs since a specific time
journalctl -u myapp.service --since "2025-01-01 12:00:00"Якщо ваша служба не запускається, журнал майже завжди містить точне повідомлення про помилку, яке пояснює чому. Це перше місце для пошуку перед внесенням будь-яких змін.
Крок 9: тестування поведінки при завантаженні
Щоб підтвердити, що служба пережить перезавантаження без ручної перевірки послідовності завантаження, ви можете імітувати це:
# Reboot the server (only if safe to do so)
sudo rebootПісля того, як сервер повернеться в мережу, перевірте стан служби ще раз:
sudo systemctl status myapp.serviceЯкщо він показує active (running), ваша служба правильно налаштована для автоматичного запуску.
Управління життєвим циклом служби
Після того, як ваша служба запущена, ви регулярно використовуватимете такі команди:
Загальні команди systemctl
# Start the service
sudo systemctl start myapp.service
# Stop the service gracefully
sudo systemctl stop myapp.service
# Restart the service (stop + start)
sudo systemctl restart myapp.service
# Reload configuration without restarting (if ExecReload is defined)
sudo systemctl reload myapp.service
# Enable automatic startup at boot
sudo systemctl enable myapp.service
# Disable automatic startup at boot
sudo systemctl disable myapp.service
# Check whether the service is enabled
sudo systemctl is-enabled myapp.service
# Check whether the service is currently active
sudo systemctl is-active myapp.service
# View the full unit file as systemd interprets it
sudo systemctl cat myapp.service
# Edit the unit file and reload in one step
sudo systemctl edit --full myapp.serviceУсунення типових проблем
Служба не запускається: “No such file or directory”
Це зазвичай означає, що ExecStart вказує на неіснуючий двійковий файл або WorkingDirectory не існує. Перевірте обидва шляхи:
which myapp
ls -l /opt/myappСлужба запускається, але негайно виходить
Перевірте журнал на власний вихід помилки програми:
journalctl -u myapp.service -n 100 --no-pagerТакож перевірте, що Type=simple правильний для вашої програми. Якщо ваш двійковий файл розгалужується сам у фоновому режимі, замість цього використовуйте Type=forking.
Помилки “Permission denied”
Користувач служби не має доступу до необхідного файлу або каталогу. Використовуйте ls -l для аудиту дозволів та sudo -u myuser для інтерактивної перевірки доступу.
Порт уже використовується
Інший процес прив’язаний до порту, який потребує ваша програма. Визначте його за допомогою:
sudo ss -tlnp | grep :<port>Служба перезапускається в циклі
Якщо Restart=on-failure викликає швидкі цикли перезапуску, systemd в кінцевому підсумку дросельує перезапуски. Перевірте StartLimitIntervalSec та StartLimitBurst у розділі [Unit] для налаштування цієї поведінки та завжди розслідуйте основну причину в журналі.
Розширені шаблони systemd для виробничих серверів
Змінні середовища та файли середовища
Ніколи не жорстко кодуйте секрети у файлах модулів. Замість цього використовуйте файл середовища:
###
on All Hosting Services
