הפעלה מחדש אוטומטית של בוט מסחר: systemd, Docker, התראות

הגדרת הפעלה מחדש אוטומטית של בוט מסחר בוט מסחר פועל 24/7. קריסה עקב שגיאת רשת, OOM, חריגה שלא טופלה, או עדכון מערכת — והתהליך מת. ללא הפעלה מחדש אוטומטית, הבוט נשאר מת עד שמפעיל מתערב. ככל שההשבתה ארוכה יותר, כך מפסידים יותר רווח וס

שירותי פיתוח בלוקצ'יין

שאלות נפוצות

העבודות האחרונות

  • image_website-b2b-advance_0.webp
    פיתוח אתר חברה B2B ADVANCE
    1450
  • image_web-applications_feedme_466_0.webp
    פיתוח אפליקציית ווב עבור FEEDME
    1309
  • image_websites_belfingroup_462_0.webp
    פיתוח אתר עבור BELFINGROUP
    1004
  • image_ecommerce_furnoro_435_0.webp
    פיתוח חנות מקוונת לחברת FURNORO
    1270
  • image_logo-advance_0.webp
    עיצוב לוגו לחברת B2B Advance
    719
  • image_crm_enviok_479_0.webp
    פיתוח אפליקציית ווב עבור Enviok
    1011

הגדרת הפעלה מחדש אוטומטית של בוט מסחר

בוט מסחר פועל 24/7. קריסה עקב שגיאת רשת, OOM, חריגה שלא טופלה או עדכון מערכת — והתהליך מת. ללא הפעלה מחדש אוטומטית, הבוט נשאר מושבת עד שמפעיל מתערב. ככל שההשבתה ארוכה יותר, כך גדלים ההפסדים והסיכון להחמצת אותות מסחר. בסביבת ייצור, אנו משיגים זמינות של 99.9% באמצעות שילוב של systemd, כיבוי מסודר והתראות. נראה כיצד להגדיר זאת באמצעות דוגמה מפרויקט אמיתי: בוט Python עם aiohttp הפועל על Ubuntu 22.04 עם 4 ליבות. אנו משתמשים ב-systemd לניהול, ב-Docker לבידוד וב-Prometheus לניטור.

systemd הוא מנהל השירותים הסטנדרטי בלינוקס. הוא יכול להפעיל מחדש תהליך אוטומטית, להגביל משאבים ולתעד. אך הגדרת Restart=always בלבד אינה מספיקה — יש צורך בהגנה מפני לולאות קריסה. נבחן שלושה מרכיבים מרכזיים: יחידת systemd, כיבוי מסודר בקוד הבוט והתראות על תקלות. עבור בוטים בקונטיינרים, אנו מוסיפים מדיניות הפעלה מחדש של Docker ובדיקות תקינות.

כיצד להגדיר systemd להפעלה מחדש אוטומטית

צור קובץ יחידה ב-/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 логи 

הפרמטרים # /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 логи מספקים הגנה מפני לולאות קריסה. בלעדיהם, בוט שממשיך לקרוס יופעל מחדש ללא הגבלה, תוך צבירת שגיאות (פוזיציות פתוחות, הזמנות כפולות). לאחר 5 קריסות מהירות, systemd עוצר את השירות ומפעיל התראה (אם הוגדרה). זה אמין פי 5 ממוניטור cron פשוט.

פרמטרי יחידת systemd: פירוט מפורט

פרמטר תיאור דוגמה
Restart מדיניות הפעלה מחדש always
RestartSec השהיה בין הפעלות מחדש 10
StartLimitBurst מגבלת הפעלות מהירות 5
StartLimitIntervalSec מרווח זמן למגבלה 60
MemoryLimit מגבלת זיכרון 2G
CPUQuota מכסת מעבד 80%

פרמטרים אלה מגבירים את היציבות: הבוט לא קורס מעומסים, ובשגיאות תכופות, systemd חוסם את ההפעלה, ומונע הפסדים עקב הזמנות כפולות.

מהו כיבוי מסודר ולמה הוא נחוץ?

לא ניתן להרוג בוט עם 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 על StartLimitBurst=5 שולח SIGTERM, ולאחר StartLimitIntervalSec=60 (ברירת מחדל 90 שניות) שולח SIGKILL. עבור בוט עם פוזיציות, 90 שניות בדרך כלל מספיקות.

Docker: חלופה לבוטים בקונטיינרים

אם הבוט פועל ב-Docker, השתמש ב-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) — הוא מפעיל מחדש על קריסה ואחרי אתחול מארח, אך לא על עצירה ידנית. בדיקת תקינות היא קריטית: 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 

דוגמה לנקודת תקינות ב-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 מדיניות הפעלה מחדש
הגנה מפני לולאות קריסה StartLimitBurst + Interval אין מובנה (רק תקינות)
כיבוי מסודר SIGTERM + TimeoutStopSec SIGTERM + stop_grace_period
ניטור תקיעות אין מובנה בדיקת תקינות
המלצה לשרתי Linux עצמאיים לתשתית קונטיינרים

מדוע יש צורך בהתראות על קריסה

עובדת ההפעלה מחדש צריכה ליצור הודעה — גם אם הבוט התאושש אוטומטית. הפתרון המינימלי הוא בוט טלגרם עם שם המארח והשעה. ב-systemd, זה נעשה דרך systemctl stop. עבור Prometheus: כלל TimeoutStopSec. קבל ייעוץ על הגדרת התראות — נמליץ על הפתרון האופטימלי לתשתית שלך.

מה כלול בהגדרת הפעלה מחדש אוטומטית (תוצרים)

  • יחידת systemd או תצורת Docker Compose עם הגנה מפני לולאות קריסה
  • יישום כיבוי מסודר המטפל בהזמנות פתוחות
  • נקודת בדיקת תקינות המאמתת את מצב הבוט והבורסה
  • הגדרת התראות (Telegram / Slack) על קריסות והפעלות חוזרות תכופות
  • בדיקות בסביבת staging לפני פריסה לייצור
  • תיעוד תצורה והוראות לצוות שלך
  • 5+ שנות ניסיון בפיתוח בלוקצ'יין — אנו מבטיחים יציבות
דוגמה ללולאת קריסה והשלכותיה

אם הבוט קורס כל 5 שניות עקב שגיאת חיבור לבורסה, ללא StartLimitBurst systemd יפעיל אותו מחדש ללא הגבלה. כל הפעלה עלולה לנסות לבטל הזמנות או ליצור חדשות, מה שמוביל לפוזיציות כפולות. עם StartLimitBurst=5, לאחר הניסיון החמישי, systemd עוצר את השירות ואתה מקבל התראה. זה חוסך ממך הפסדים כספיים.

צור קשר כדי להגדיר את בוט המסחר שלך — אנו מבטיחים פעילות יציבה 24/7. קבל ייעוץ על systemd, Docker והגדרת התראות.