{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Running Your Trading Bot 24/7 with nohup\n", "\n", "## Option 1: nohup (No Hang Up) - Simplest Method\n", "\n", "**Best for:** Beginners, single bot deployment, simple setups\n", "\n", "**What nohup does:**\n", "- Runs your process immune to hangups (SIGHUP signals)\n", "- Continues running even after you close SSH connection\n", "- Redirects output to files for logging\n", "- Simple and lightweight solution" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Step 1: Basic nohup Usage\n", "\n", "**⚠️ Run these commands on your server via SSH, not in Jupyter!**" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "source": [ "# Basic nohup command\n", "# This runs your bot in background and logs output to nohup.out\n", "nohup python3 main.py &\n", "\n", "# Better version - custom log file\n", "nohup python3 main.py > bot.log 2>&1 &\n", "\n", "# Even better - with timestamp in log filename\n", "nohup python3 main.py > bot_$(date +%Y%m%d_%H%M%S).log 2>&1 &" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Command Breakdown:\n", "- `nohup` - Makes process immune to hangup signals\n", "- `python3 main.py` - Your bot command\n", "- `> bot.log` - Redirect stdout (normal output) to bot.log\n", "- `2>&1` - Redirect stderr (errors) to same file as stdout\n", "- `&` - Run in background" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Step 2: Using PID Files for Better Management" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "source": [ "# Start bot and save Process ID (PID) to file\n", "nohup python3 main.py > bot.log 2>&1 &\n", "echo $! > bot.pid\n", "\n", "# Check what PID was saved\n", "cat bot.pid\n", "\n", "# Verify the process is running\n", "ps aux | grep $(cat bot.pid)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Step 3: Managing Your Bot" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "source": [ "# Check if bot is running\n", "if kill -0 $(cat bot.pid) 2>/dev/null; then\n", " echo \"Bot is running with PID $(cat bot.pid)\"\n", "else\n", " echo \"Bot is not running\"\n", "fi\n", "\n", "# View live logs\n", "tail -f bot.log\n", "\n", "# View last 50 lines of logs\n", "tail -n 50 bot.log\n", "\n", "# Search for errors in logs\n", "grep -i error bot.log" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Step 4: Stopping Your Bot" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "source": [ "# Graceful stop (recommended)\n", "kill -TERM $(cat bot.pid)\n", "\n", "# Force stop if graceful doesn't work\n", "kill -KILL $(cat bot.pid)\n", "\n", "# Clean up PID file\n", "rm bot.pid\n", "\n", "# One-liner to stop and cleanup\n", "kill $(cat bot.pid) && rm bot.pid" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Step 5: Create Start/Stop Scripts\n", "\n", "### Create start_bot.sh script" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "source": [ "# Create start script\n", "nano start_bot.sh" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Contents of start_bot.sh:**" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "source": [ "#!/bin/bash\n", "\n", "# Check if bot is already running\n", "if [ -f bot.pid ] && kill -0 $(cat bot.pid) 2>/dev/null; then\n", " echo \"Bot is already running with PID $(cat bot.pid)\"\n", " exit 1\n", "fi\n", "\n", "# Start the bot\n", "echo \"Starting trading bot...\"\n", "cd /root/trading-bot\n", "nohup python3 main.py > bot_$(date +%Y%m%d_%H%M%S).log 2>&1 &\n", "echo $! > bot.pid\n", "\n", "echo \"Bot started with PID $(cat bot.pid)\"\n", "echo \"Log file: bot_$(date +%Y%m%d_%H%M%S).log\"\n", "echo \"To view logs: tail -f bot_$(date +%Y%m%d_%H%M%S).log\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Create stop_bot.sh script" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "source": [ "# Create stop script\n", "nano stop_bot.sh" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Contents of stop_bot.sh:**" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "source": [ "#!/bin/bash\n", "\n", "# Check if PID file exists\n", "if [ ! -f bot.pid ]; then\n", " echo \"No PID file found. Bot may not be running.\"\n", " exit 1\n", "fi\n", "\n", "# Get PID\n", "PID=$(cat bot.pid)\n", "\n", "# Check if process is running\n", "if ! kill -0 $PID 2>/dev/null; then\n", " echo \"Process $PID is not running. Cleaning up PID file.\"\n", " rm bot.pid\n", " exit 1\n", "fi\n", "\n", "# Stop the bot\n", "echo \"Stopping trading bot (PID: $PID)...\"\n", "kill -TERM $PID\n", "\n", "# Wait for graceful shutdown\n", "sleep 5\n", "\n", "# Check if still running\n", "if kill -0 $PID 2>/dev/null; then\n", " echo \"Process still running. Force killing...\"\n", " kill -KILL $PID\n", "fi\n", "\n", "# Clean up\n", "rm bot.pid\n", "echo \"Bot stopped successfully.\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Make scripts executable" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "source": [ "chmod +x start_bot.sh\n", "chmod +x stop_bot.sh\n", "\n", "# Now you can use:\n", "./start_bot.sh\n", "./stop_bot.sh" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Step 6: Enhanced Python Bot with PID Management\n", "\n", "**Add this to your main.py to handle PID files properly:**" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "source": [ "import os\n", "import sys\n", "import atexit\n", "import signal\n", "from datetime import datetime\n", "\n", "# PID file management\n", "PID_FILE = 'bot.pid'\n", "\n", "def write_pid_file():\n", " \"\"\"Write current process PID to file\"\"\"\n", " with open(PID_FILE, 'w') as f:\n", " f.write(str(os.getpid()))\n", " print(f\"PID {os.getpid()} written to {PID_FILE}\")\n", "\n", "def cleanup_pid_file():\n", " \"\"\"Remove PID file on exit\"\"\"\n", " if os.path.exists(PID_FILE):\n", " os.remove(PID_FILE)\n", " print(f\"Cleaned up {PID_FILE}\")\n", "\n", "def signal_handler(signum, frame):\n", " \"\"\"Handle termination signals gracefully\"\"\"\n", " print(f\"\\nReceived signal {signum}. Shutting down gracefully...\")\n", " cleanup_pid_file()\n", " sys.exit(0)\n", "\n", "# Set up signal handlers for graceful shutdown\n", "signal.signal(signal.SIGTERM, signal_handler)\n", "signal.signal(signal.SIGINT, signal_handler)\n", "\n", "# Register cleanup function\n", "atexit.register(cleanup_pid_file)\n", "\n", "# Write PID file when starting\n", "write_pid_file()\n", "\n", "# Your trading bot code here\n", "def main():\n", " print(f\"Trading bot started at {datetime.now()}\")\n", " \n", " while True:\n", " try:\n", " # Your trading logic here\n", " print(f\"Bot running... {datetime.now()}\")\n", " time.sleep(60) # Sleep for 1 minute\n", " \n", " except KeyboardInterrupt:\n", " print(\"\\nKeyboard interrupt received. Shutting down...\")\n", " break\n", " except Exception as e:\n", " print(f\"Error occurred: {e}\")\n", " time.sleep(10) # Wait before retrying\n", "\n", "if __name__ == \"__main__\":\n", " main()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Step 7: Monitoring and Troubleshooting" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "source": [ "# Check all your Python processes\n", "ps aux | grep python3\n", "\n", "# Monitor system resources\n", "top\n", "# or\n", "htop\n", "\n", "# Check disk space (logs can grow large)\n", "df -h\n", "\n", "# Check memory usage\n", "free -h\n", "\n", "# Find large log files\n", "find . -name \"*.log\" -size +10M\n", "\n", "# Rotate logs (keep last 100 lines)\n", "tail -n 100 bot.log > bot.log.tmp && mv bot.log.tmp bot.log" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Common Issues and Solutions\n", "\n", "### Issue 1: \"Bot.pid file exists but process not running\"\n", "**Solution:** Clean up stale PID file\n", "```bash\n", "rm bot.pid\n", "./start_bot.sh\n", "```\n", "\n", "### Issue 2: \"Permission denied\"\n", "**Solution:** Check file permissions\n", "```bash\n", "chmod +x start_bot.sh stop_bot.sh\n", "chmod 755 main.py\n", "```\n", "\n", "### Issue 3: \"Module not found errors\"\n", "**Solution:** Install missing packages\n", "```bash\n", "pip3 install package_name\n", "```\n", "\n", "### Issue 4: \"Log files growing too large\"\n", "**Solution:** Implement log rotation\n", "```bash\n", "# Add to crontab for daily log rotation\n", "0 0 * * * /root/trading-bot/rotate_logs.sh\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Pros and Cons Summary\n", "\n", "### ✅ Pros:\n", "- **Simple to use** - just one command\n", "- **Lightweight** - minimal system overhead\n", "- **Built-in** - available on all Unix/Linux systems\n", "- **Perfect for single bot** deployments\n", "- **Easy debugging** - direct log file access\n", "\n", "### ❌ Cons:\n", "- **No automatic restart** on crash\n", "- **Manual management** - need scripts for start/stop\n", "- **No built-in monitoring** - need external tools\n", "- **PID file management** - manual cleanup needed\n", "- **Not suitable for multiple bots** - becomes complex\n", "\n", "### 🎯 Best Use Cases:\n", "- Learning and development\n", "- Single trading bot deployment\n", "- Short to medium-term trading strategies\n", "- When you want full control over the process" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.5" } }, "nbformat": 4, "nbformat_minor": 4 }