Настройка автоматического перезапуска торгового бота
Торговый бот работает 24/7. Сбой из-за сетевой ошибки, OOM, необработанного исключения или обновления системы — и процесс падает. Без автоперезапуска бот остаётся мёртвым, пока не вмешается оператор. Чем дольше простой, тем больше упущенная прибыль и риск пропустить торговые сигналы. В production мы добиваемся uptime 99.9% за счёт связки systemd, graceful shutdown и алертов. Расскажу, как это настроить, на примере реального проекта: бот на Python с aiohttp, работающий на Ubuntu 22.04 с 4 ядрами. Мы используем systemd для управления, Docker для изоляции и Prometheus для мониторинга.
systemd — стандартный менеджер сервисов в Linux. Он умеет автоматически перезапускать процесс, ограничивать ресурсы и логировать. Но одной настройки Restart=always недостаточно — нужна защита от crash loop. Рассмотрим три ключевых компонента: systemd unit, graceful shutdown в коде бота и алерты при сбоях. Для контейнеризированных ботов дополним Docker restart policy и health check.
Как настроить systemd для автоматического перезапуска?
Создайте unit-файл в /etc/systemd/system/ с параметрами Restart=always и RestartSec=10. Дополнительно укажите StartLimitBurst=5 и StartLimitIntervalSec=60, чтобы избежать бесконечного перезапуска при критической ошибке. Активируйте сервис: systemctl enable trading-bot.
# /etc/systemd/system/trading-bot.service [Unit] Description=Trading Bot After=network-online.target Wants=network-online.target [Service] Type=simple User=botuser WorkingDirectory=/opt/trading-bot ExecStart=/opt/trading-bot/venv/bin/python -u bot.py Restart=always RestartSec=10 StartLimitIntervalSec=60 StartLimitBurst=5 EnvironmentFile=/opt/trading-bot/.env MemoryLimit=2G CPUQuota=80% StandardOutput=journal StandardError=journal SyslogIdentifier=trading-bot [Install] WantedBy=multi-user.target Активация:
systemctl daemon-reload systemctl enable trading-bot systemctl start trading-bot journalctl -u trading-bot -f # live логи Параметр StartLimitBurst=5 + StartLimitIntervalSec=60 — защита от crash loop. Без неё бот при постоянных падениях будет непрерывно перезапускаться, накапливая ошибки (открытые позиции, дублирующиеся ордера). После 5 быстрых падений systemd остановит службу и отправит алерт (если настроен). Это в 5 раз надёжнее, чем простой cron-мониторинг.
Параметры systemd unit: подробный разбор
| Параметр | Описание | Пример |
|---|---|---|
| Restart | Политика перезапуска | always |
| RestartSec | Пауза между рестартами | 10 |
| StartLimitBurst | Лимит быстрых перезапусков | 5 |
| StartLimitIntervalSec | Интервал для лимита | 60 |
| MemoryLimit | Ограничение памяти | 2G |
| CPUQuota | Квоты CPU | 80% |
Эти параметры повышают стабильность: бот не падает из‑за перегрузок, а при частых ошибках systemd блокирует запуск, предотвращая потерю средств из‑за двойных ордеров.
Что такое graceful shutdown и зачем он нужен?
Бота нельзя убивать SIGKILL — можно оставить открытые ордера, незафиксированные позиции, неотправленные алерты. Обрабатываем SIGTERM:
import signal import asyncio class TradingBot: def __init__(self): self.running = True self.open_orders: list = [] async def shutdown(self): self.running = False for order_id in self.open_orders: try: await self.exchange.cancel_order(order_id) except Exception as e: logger.error(f"Failed to cancel order {order_id}: {e}") logger.info("Graceful shutdown complete") async def run(self): loop = asyncio.get_event_loop() loop.add_signal_handler( signal.SIGTERM, lambda: asyncio.create_task(self.shutdown()) ) while self.running: try: await self.main_loop() except Exception as e: logger.exception(f"Error in main loop: {e}") await asyncio.sleep(5) systemd при systemctl stop шлёт SIGTERM, затем через TimeoutStopSec (default 90 сек) — SIGKILL. Для бота с позициями 90 секунд обычно достаточно.
Docker: альтернатива для контейнеризированных ботов
Если бот запускается в Docker, используйте restart: unless-stopped — он перезапускает при падении и при перезагрузке хоста, но не при ручной остановке. Health check критически важен: Docker перезапускает контейнер только при полном падении, а зависание без ошибки не заметит.
# docker-compose.yml services: trading-bot: image: trading-bot:latest restart: unless-stopped env_file: .env volumes: - ./data:/app/data - ./logs:/app/logs mem_limit: 2g logging: driver: "json-file" options: max-size: "100m" max-file: "5" healthcheck: test: ["CMD", "python", "-c", "import requests; requests.get('http://localhost:8080/health', timeout=5)"] interval: 30s timeout: 10s retries: 3 start_period: 60s Пример health-эндпоинта на aiohttp:
from aiohttp import web async def health_check(request): last_loop_age = time.time() - bot.last_loop_time if last_loop_age > 300: return web.Response(status=503, text=f"Bot stuck: last loop {last_loop_age:.0f}s ago") if not bot.exchange_connected: return web.Response(status=503, text="Exchange disconnected") return web.Response(status=200, text="OK") app = web.Application() app.router.add_get('/health', health_check) Сравнение systemd и Docker для автоперезапуска
| Параметр | systemd | Docker |
|---|---|---|
| Механизм перезапуска | systemd unit | restart policy |
| Защита от crash loop | StartLimitBurst + Interval | Нет встроенной (только health) |
| Graceful shutdown | SIGTERM + TimeoutStopSec | SIGTERM + stop_grace_period |
| Мониторинг зависаний | Нет встроенного | Health check |
| Рекомендация | Для собственных Linux‑серверов | Для контейнеризированной инфраструктуры |
Почему нужны алерты при падении?
Сам факт перезапуска должен генерировать уведомление — даже если бот восстановился автоматически. Минимальное решение — Telegram-бот с именем хоста и временем. В systemd это делается через OnFailure=trading-bot-notify.service. Для Prometheus: правило changes(process_start_time_seconds{job="trading-bot"}[5m]) > 0. Получите консультацию по настройке алертов — подскажем оптимальное решение для вашей инфраструктуры.
Что входит в настройку автоматического перезапуска (deliverables)
- Конфигурация systemd unit или Docker compose с защитой от crash loop
- Реализация graceful shutdown с обработкой открытых ордеров
- Health check endpoint с проверкой состояния бота и биржи
- Настройка алертов (Telegram / Slack) при падении и частых рестартах
- Тестирование на staging-окружении до выхода в production
- Документация конфигурации и инструкция для вашей команды
- 5+ лет опыта в блокчейн-разработке — гарантируем стабильность
Пример crash loop и его последствия
Если бот падает каждые 5 секунд из-за ошибки подключения к бирже, без StartLimitBurst systemd будет перезапускать его бесконечно. Каждый запуск может попытаться отменить ордера или создать новые, что приведёт к двойным позициям. С StartLimitBurst=5 после пятой попытки systemd остановит сервис, и вы получите алерт. Это спасёт от финансовых потерь.
Закажите настройку торгового бота в компании — мы обеспечим стабильную работу 24/7. Получите консультацию по конфигурации systemd, Docker и алертов.







