Налаштування автоматичного перезапуску торгового бота
Торговий бот працює 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 та алертів.







