Своя служба systemd: автозапуск чего угодно на Linux

Администрирование
Своя служба systemd: автозапуск чего угодно на Linux

Своя служба systemd — самый надёжный способ настроить автозапуск в Linux для чего угодно: Telegram-бота, Node.js-приложения, парсера, самописного API. Один unit-файл на 10 строк — и ваш процесс стартует вместе с сервером, сам поднимается после падения и пишет логи в одно предсказуемое место. В этой статье разберём структуру unit-файла, параметр Restart=always, управление через systemctl и отладку через journalctl — всё на примерах для Ubuntu 24.04 LTS.

Зачем нужна своя служба systemd, если есть screen и nohup

Новички обычно запускают скрипты через screen, tmux или nohup. Это работает ровно до первой перезагрузки VPS или первого необработанного исключения. Дальше — процесс мёртв, а вы узнаёте об этом от пользователей.

Systemd — это система инициализации, которая управляет всеми процессами в современных дистрибутивах (Ubuntu, Debian, AlmaLinux, Rocky Linux). Оформив программу как службу, вы получаете:

  • Автозапуск при загрузке — сервер перезагрузился, служба поднялась сама;
  • Автоперезапуск после сбоя — упал процесс, systemd перезапустил его через заданное число секунд;
  • Централизованные логи — весь stdout/stderr попадает в journald, не нужно городить перенаправления в файлы;
  • Единое управлениеstart, stop, restart, status одними и теми же командами;
  • Ограничения ресурсов — можно лимитировать память и CPU конкретной службы.

Подробное сравнение способов запуска скриптов мы разбирали в статье про запуск Python-скриптов 24/7 — здесь сосредоточимся именно на systemd.

Анатомия unit-файла: три секции

Unit-файл — это текстовый файл в формате INI. Свои службы кладут в каталог /etc/systemd/system/, имя файла — это имя службы: mybot.service → служба mybot. Минимальный рабочий unit-файл выглядит так:

[Unit]
Description=My Telegram bot
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=botuser
WorkingDirectory=/opt/mybot
ExecStart=/usr/bin/python3 /opt/mybot/bot.py
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

Что означает каждая секция:

[Unit] — описание и зависимости

  • Description — человекочитаемое имя, видно в systemctl status;
  • After=network-online.target — стартовать после того, как поднялась сеть. Для ботов и всего, что ходит в интернет, — обязательно;
  • Wants= — мягкая зависимость: подтянуть указанный target, но не падать, если он недоступен.

[Service] — как запускать процесс

  • Type=simple — процесс в ExecStart и есть сама служба (подходит для 95% случаев). Для программ, которые сами уходят в фон, используют Type=forking;
  • User — от кого запускать. Никогда не запускайте бота от root без необходимости;
  • WorkingDirectory — рабочий каталог. Без него относительные пути в скрипте сломаются;
  • ExecStart — команда запуска. Только абсолютные пути: systemd не знает ваш $PATH из .bashrc;
  • Restart и RestartSec — политика перезапуска, о ней ниже.

[Install] — когда включать

WantedBy=multi-user.target означает «запускать при обычной загрузке системы». Именно эта строка делает возможным systemctl enable.

Пошагово: служба для своего скрипта за 5 минут

  1. Проверьте ручной запуск. Программа должна работать от нужного пользователя по абсолютному пути: sudo -u botuser /usr/bin/python3 /opt/mybot/bot.py. Если тут ошибка — служба её унаследует.
  2. Создайте unit-файл: sudo nano /etc/systemd/system/mybot.service — и вставьте шаблон выше, поправив пути и пользователя.
  3. Перечитайте конфигурацию:
   sudo systemctl daemon-reload

Эту команду нужно повторять после каждого изменения unit-файла.

  1. Запустите и проверьте:
   sudo systemctl start mybot
   systemctl status mybot

В статусе должно быть active (running) зелёным.

  1. Включите автозапуск:
   sudo systemctl enable mybot

Теперь после ребута служба поднимется сама. Команда enable --now объединяет включение и запуск.

На VPS от Cheap-Host сервер выдаётся за 45–60 секунд после оплаты, так что весь путь «купил сервер → бот работает как служба» реально пройти минут за десять. Для пары ботов и скриптов достаточно тарифа Start за 450 ₽/мес — 6 vCPU и 8 ГБ RAM с запасом.

Restart=always: служба, которая не умирает

Параметр Restart определяет, что делать, когда процесс завершился. Основные значения:

ЗначениеКогда перезапускатьКому подходит
noНикогда (по умолчанию)Разовые задачи
on-failureТолько при ненулевом коде выхода или сигналеСкрипты, которые могут штатно завершаться
alwaysПри любом завершении, даже успешномБоты, серверы, демоны — всё, что должно жить вечно

RestartSec=5 задаёт паузу перед перезапуском. Не ставьте 0: если приложение падает мгновенно (например, нет доступа к API), вы получите цикл быстрых рестартов и упрётесь в лимит — по умолчанию systemd разрешает 5 запусков за 10 секунд, после чего переводит службу в состояние failed. Для «упрямого» перезапуска лимит можно ослабить:

[Unit]
StartLimitIntervalSec=60
StartLimitBurst=10

Сбросить счётчик неудач вручную: sudo systemctl reset-failed mybot.

journalctl: где смотреть логи службы

Всё, что служба пишет в stdout и stderr, попадает в журнал systemd. Основные команды:

# Последние 50 строк службы
journalctl -u mybot -n 50

# Следить за логом в реальном времени (аналог tail -f)
journalctl -u mybot -f

# Логи за сегодня
journalctl -u mybot --since today

# Только ошибки и хуже
journalctl -u mybot -p err

Пара практических советов. Во-первых, для Python добавьте в unit-файл Environment=PYTHONUNBUFFERED=1, иначе вывод будет появляться в журнале с задержкой из-за буферизации. Во-вторых, проверьте, что журнал персистентный: если каталога /var/log/journal нет, логи живут в памяти и пропадают при ребуте. Лечится так:

sudo mkdir -p /var/log/journal
sudo systemd-tmpfiles --create --prefix /var/log/journal
sudo systemctl restart systemd-journald

Именно связка systemctl status + journalctl -u закрывает 90% вопросов «почему не работает». Это сильно удобнее, чем искать разбросанные по диску лог-файлы, — тот же подход выручает и при самостоятельном мониторинге VPS.

Полезные параметры для реальных задач

Несколько строк, которые стоит знать помимо базового шаблона:

  • Environment=TOKEN=abc123 — переменные окружения прямо в unit-файле;
  • EnvironmentFile=/opt/mybot/.env — то же, но из файла (удобно для секретов, не забудьте chmod 600);
  • ExecStartPre= — команда перед запуском, например миграции базы;
  • MemoryMax=512M — жёсткий потолок памяти: служба не съест весь VPS;
  • CPUQuota=50% — ограничение процессора;
  • NoNewPrivileges=true и ProtectSystem=full — базовое «песочничание» процесса.

Таким же способом оформляют автозапуск чего угодно: Node.js-приложений (хотя там популярен и PM2 — сравнение есть в статье про деплой Node.js на VPS), Go-бинарников, Java-серверов, самописных прокси. А для задач по расписанию у systemd есть таймеры — более гибкая альтернатива классическому cron: они умеют догонять пропущенные запуски через Persistent=true и наследуют все возможности служб.

Частые ошибки новичков

  • Забыли daemon-reload после правки unit-файла — systemd работает со старой версией;
  • Относительные пути в ExecStart — служба не находит интерпретатор или скрипт;
  • Рассчитывали на .bashrc — виртуальные окружения Python активируйте явно: ExecStart=/opt/mybot/venv/bin/python /opt/mybot/bot.py;
  • Сделали start, но не enable — после перезагрузки служба не поднялась;
  • Запуск от root без причины — при взломе приложения атакующий получает весь сервер.

FAQ

Чем systemd-служба лучше запуска через screen или nohup?

Служба переживает перезагрузку, сама перезапускается после падения, пишет логи в journald и управляется стандартным systemctl. Screen и nohup после ребута оставляют вас с мёртвым процессом.

Почему служба не стартует, хотя скрипт вручную работает?

Почти всегда — пути или окружение: systemd не читает ваш .bashrc. Проверьте абсолютные пути в ExecStart, задайте WorkingDirectory и переменные через Environment=. Причину покажет journalctl -u имя -n 50.

Что делать, если служба падает и перезапускается по кругу?

Смотрите причину в journalctl и чините её. После срабатывания лимита запусков выполните systemctl reset-failed. Для нестабильных приложений увеличьте RestartSec и ослабьте StartLimitBurst.

Можно ли запускать службу не от root?

Нужно: добавьте User= и Group= в секцию [Service]. Приложению почти никогда не нужны права root, а безопасность выигрывает заметно.

Какой сервер нужен, чтобы держать свои службы 24/7?

Systemd сам по себе ресурсов не требует — считайте аппетиты ваших приложений. Несколько ботов и скриптов спокойно живут на VPS Start у Cheap-Host: 6 vCPU, 8 ГБ RAM, NVMe за 450 ₽/мес.

Вывод

Unit-файл из десяти строк превращает любой скрипт в полноценный сервис: автозапуск при загрузке, Restart=always на случай падений и понятные логи в journalctl. Один раз разобравшись с шаблоном, вы будете оформлять так каждый процесс, который должен работать без присмотра. Если для этих задач нужен сервер — у Cheap-Host тариф Start от 450 ₽/мес: KVM с полным root, NVMe-диски, безлимитный трафик и выдача сервера за минуту. Тарифы — на cheap-host.onl.

Читайте также