DevOpsLinuxДеплой

Как держать процесс запущенным 24/7: systemd, pm2 и Docker

6 мин чтения

Команда python bot.py, запущенная по SSH, живёт ровно до закрытия терминала. Сессия оборвалась — процесс получил SIGHUP и умер, бот замолчал, фоновая обработка встала. Для прода нужно не «запустить», а держать запущенным: чтобы процесс поднимался после краша, после OOM, после перезагрузки сервера — без участия человека.

Разберём три рабочих способа: systemd, pm2 и restart-политики Docker, — и чем они отличаются.

Почему nohup и screen не подходят

Первое, что подсказывает поиск, — nohup python bot.py & или запуск внутри screen/tmux. Это решает только одну проблему: процесс переживает выход из сессии. Но он по-прежнему:

  • не перезапускается, если упал с ошибкой;
  • не поднимается после перезагрузки сервера;
  • не пишет логи в стандартное место;
  • не имеет управляемого старта и остановки.

nohup и screen — это «запустил и забыл, пока не упадёт». Для прода нужен супервизор — процесс-менеджер, который следит за приложением и поднимает его обратно.

systemd — стандарт для Linux

В любом современном дистрибутиве уже есть systemd, и для большинства приложений это лучший выбор: ничего ставить не нужно, перезапуск и автозапуск встроены, логи идут в journald.

Unit-файл /etc/systemd/system/mybot.service:

[Unit]
Description=Telegram bot
After=network.target

[Service]
Type=simple
User=appuser
WorkingDirectory=/opt/mybot
ExecStart=/opt/mybot/.venv/bin/python bot.py
Restart=always
RestartSec=3
Environment=PYTHONUNBUFFERED=1

[Install]
WantedBy=multi-user.target

Ключевые строки — Restart=always (поднимать после любого завершения) и RestartSec=3 (пауза перед рестартом, чтобы при падении на старте не молотить рестартами вплотную). Сам по себе крах-цикл это не останавливает: за это отвечает встроенный лимит StartLimitBurst — по умолчанию после 5 запусков за 10 секунд systemd переводит сервис в состояние failed. Активация:

sudo systemctl daemon-reload
sudo systemctl enable --now mybot
sudo systemctl status mybot
journalctl -u mybot -f   # логи в реальном времени

enable ставит автозапуск при загрузке, --now сразу стартует сервис. С этого момента процесс переживает и краш, и перезагрузку.

pm2 — для Node.js

Если приложение на Node.js, удобен pm2 — менеджер процессов с человеко-понятным CLI, логами и мониторингом из коробки.

npm install -g pm2

pm2 start app.js --name api
pm2 logs api
pm2 restart api

Чтобы pm2 поднимал процессы после перезагрузки сервера, список нужно зафиксировать:

pm2 startup      # выведет команду для регистрации в systemd — выполнить её
pm2 save         # сохранить текущий список процессов

Важная деталь: без pm2 save после перезагрузки список окажется пустым. И, по сути, pm2 startup всё равно регистрирует pm2 как сервис systemd — то есть под капотом это надстройка над тем же механизмом.

Docker restart policies

Если приложение уже в контейнере, отдельный супервизор не нужен — рестартом управляет сам Docker через политику перезапуска.

# docker-compose.yml
services:
  bot:
    build: .
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "python", "healthcheck.py"]
      interval: 30s
      timeout: 5s
      retries: 3

Политика unless-stopped поднимает контейнер после краша и после перезагрузки демона, но не трогает контейнер, если он остановлен вручную. Альтернатива — always. Через чистый docker run то же самое: --restart unless-stopped. healthcheck позволяет Docker понимать, что процесс жив не только как PID, но и функционально.

Что выбрать

ИнструментКогда подходитАвтозапуск при ребутеЛоги
systemdлюбые приложения на «голом» сервередаjournald
pm2Node.js, нужен удобный CLI и мониторингда, после pm2 saveсвой лог-файл
Docker restartприложение уже контейнеризованода (unless-stopped)docker logs

Если коротко: для контейнера — restart-политика, для Node.js без контейнера — pm2, во всех остальных случаях — systemd.

Чего эти инструменты не делают

Супервизор держит процесс живым — и только. Он не выкатывает новую версию по git push, не выпускает и не продлевает SSL-сертификат, не делает бэкапы базы, не следит за местом на диске и не присылает алерт, когда приложение упало в три ночи. Это всё — отдельные задачи, которые в self-hosted-сетапе придётся настраивать и обслуживать поверх.

То есть supervised-процесс — это необходимый минимум для прода, но не вся эксплуатация. Где-то рядом всегда оказываются деплой, сертификаты, мониторинг и бэкапы.

Чеклист

  • Процесс запускается через супервизор, а не nohup/screen.
  • Включён автоматический перезапуск после краша (Restart=always / restart: unless-stopped).
  • Включён автозапуск после перезагрузки сервера (enable / pm2 save / restart-политика).
  • Логи пишутся в стандартное место и доступны (journalctl / docker logs).
  • Есть пауза между рестартами, чтобы не зациклиться при падении на старте.

Managed-платформа берёт супервайзинг на себя: процесс перезапускается автоматически, поднимается после сбоя и проходит health-check без unit-файлов и pm2 save. Например, на Hostim бот или воркер работают 24/7 без serverless-засыпания, а рядом сразу есть деплой по git push, SSL и managed-база — то есть весь тот «слой поверх супервизора», который иначе пришлось бы собирать вручную.

Читать дальше