Службы systemd: systemctl, статус, логи и своя служба для бота
Как управлять службами через systemctl, читать статус и логи через journalctl и оформить скрипт или Telegram-бота как службу с автозапуском и перезапуском после падения. Ubuntu, Debian, AlmaLinux.

Nginx, база данных, Docker и SSH работают на сервере постоянно, сами поднимаются после перезагрузки и перезапускаются, если упали. Всё это делает systemd, а управляют им через systemctl. Та же механика доступна и вашим программам: любой скрипт за пять минут превращается в службу, которая работает круглосуточно без открытого терминала.
Для экспериментов подойдёт любой VPS с Ubuntu или Debian; на tanaka.host сервер можно взять на день-два, пройти инструкцию и удалить без лишних трат.
Как это работает
При загрузке ядро запускает процесс номер 1 — это systemd. Он поднимает всё остальное в правильном порядке и следит за этим до выключения. Каждая служба описана небольшим текстовым файлом — юнитом с расширением .service: какую программу запустить, от чьего имени, после каких других служб и что делать, если она завершилась.
Процесс службы и всё, что он породит, systemd кладёт в отдельную группу. Поэтому stop завершает их все, а не только главный, а в статусе видно память и процессорное время всей группы. Вывод программы в консоль не теряется, а попадает в журнал, откуда его читает journalctl. Именно поэтому службе не нужен терминал и ей всё равно, подключены вы по SSH или нет.
Два независимых действия, которые часто путают:
| Действие | Команда | Что происходит |
|---|---|---|
| запустить | start |
служба работает прямо сейчас, после перезагрузки не поднимется |
| включить | enable |
будет запускаться при загрузке, но сейчас не стартует |
| оба сразу | enable --now |
то, что обычно и нужно |
И третье: если в юните стоит Restart=always, после падения процесса systemd подождёт заданную паузу и запустит его снова.
1. Статус службы
systemctl status nginx
Важное в первых строках:
- Loaded — где лежит юнит и после
;состояние автозапуска:enabledилиdisabled; - Active —
active (running)работает,inactive (dead)остановлена,failedупала; - Main PID — главный процесс.
Если вывод не влезает в экран, откроется просмотрщик, выход — q.
2. Управление
systemctl start nginx # запустить
systemctl stop nginx # остановить
systemctl restart nginx # перезапустить
systemctl reload nginx # перечитать настройки без остановки, если служба умеет
systemctl enable nginx # включить автозапуск
systemctl disable nginx # выключить автозапуск
systemctl enable --now nginx # включить автозапуск и сразу запустить
Для скриптов удобны короткие проверки:
systemctl is-active nginx
systemctl is-enabled nginx
Что работает и что упало:
systemctl list-units --type=service --state=running
systemctl --failed
3. Логи службы
# Последние 50 строк
journalctl -u nginx -n 50
# В реальном времени, выход по Ctrl+C
journalctl -u nginx -f
# За последний час
journalctl -u nginx --since "1 hour ago"
Подробнее про журнал — в статье логи Linux и journalctl.
4. Своя служба
Допустим, есть Python-скрипт — например, Telegram-бот — и он должен работать всегда. Запущенный в терминале, он умрёт вместе с SSH-сессией. Делаем службу.
Отдельный пользователь без права входа, чтобы бот не получил лишних прав даже при уязвимости в коде:
useradd -r -s /usr/sbin/nologin appuser
Скрипт лежит в /opt/mybot/bot.py, папка принадлежит этому пользователю:
chown -R appuser:appuser /opt/mybot
Файл юнита:
nano /etc/systemd/system/mybot.service
[Unit]
Description=My Telegram bot
After=network-online.target
Wants=network-online.target
[Service]
User=appuser
WorkingDirectory=/opt/mybot
ExecStart=/usr/bin/python3 /opt/mybot/bot.py
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
Сохраните (Ctrl+O, Enter, Ctrl+X), сообщите systemd о новом файле, включите и проверьте:
systemctl daemon-reload
systemctl enable --now mybot
systemctl status mybot
Что означают строки:
AfterиWantsсnetwork-online.targetоткладывают запуск, пока не поднимется сеть;User— от чьего имени работает скрипт;WorkingDirectory— папка, где скрипт ищет свои файлы;ExecStart— команда запуска с полным путём к интерпретатору; путь узнаётся черезwhich python3;Restart=alwaysиRestartSec=5— перезапуск через 5 секунд после любого завершения;WantedBy=multi-user.target— автозапуск при загрузке.
Проверить автоперезапуск просто: kill главного процесса, и через пять секунд systemctl status mybot снова покажет active (running).
После каждой правки юнита —
systemctl daemon-reload, затемsystemctl restart mybot. Без первой команды systemd продолжит пользоваться старой версией файла. Проверка на ошибки:systemd-analyze verify /etc/systemd/system/mybot.service.
Живой пример с виртуальным окружением и токеном в отдельном файле — в статье Telegram-бот как служба systemd.
Частые ошибки
status=203/EXEC. systemd не смог запустить программу из ExecStart. Типичный случай — /usr/bin/python вместо /usr/bin/python3. Проверьте путь через which. Если запускаете скрипт напрямую, у него должно быть право x и первая строка #!/usr/bin/env python3.
Unit mybot.service could not be found. Файл не в /etc/systemd/system/, называется иначе, чем в команде, или не выполнен daemon-reload.
Служба перезапускается по кругу. Программа падает сразу после старта, Restart=always поднимает её снова. Причина в journalctl -u mybot -n 50: ошибка в скрипте, нет библиотеки или нет прав на файлы.
Удалить свою службу
systemctl disable --now mybot
rm /etc/systemd/system/mybot.service
systemctl daemon-reload
Для задач по расписанию, а не постоянной работы, вместо службы нужен cron.