From b114d29716f40dc745fd2111a1167e6106ee29e6 Mon Sep 17 00:00:00 2001 From: Jakub Polec Date: Sat, 28 Jun 2025 16:08:28 +0200 Subject: [PATCH] Session_06 code --- Session_06/Notebooks/hetzner_setup.ipynb | 785 ++++++++++++ Session_06/Notebooks/method_nohup.ipynb | 455 +++++++ Session_06/Notebooks/method_screen_tmux.ipynb | 636 ++++++++++ Session_06/Notebooks/method_ssytemd.ipynb | 1117 +++++++++++++++++ Session_06/_files_ | 0 Session_06/algorithm-service.sh | 170 +++ 6 files changed, 3163 insertions(+) create mode 100644 Session_06/Notebooks/hetzner_setup.ipynb create mode 100644 Session_06/Notebooks/method_nohup.ipynb create mode 100644 Session_06/Notebooks/method_screen_tmux.ipynb create mode 100644 Session_06/Notebooks/method_ssytemd.ipynb delete mode 100644 Session_06/_files_ create mode 100755 Session_06/algorithm-service.sh diff --git a/Session_06/Notebooks/hetzner_setup.ipynb b/Session_06/Notebooks/hetzner_setup.ipynb new file mode 100644 index 0000000..a8edb43 --- /dev/null +++ b/Session_06/Notebooks/hetzner_setup.ipynb @@ -0,0 +1,785 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Hetzner VPS Setup Guide - Complete Instructions\n", + "\n", + "## Session 6: Live Trading & Deployment\n", + "\n", + "**Today's Objectives:**\n", + "- Secure API key management & best practices\n", + "- Choose the right deployment platform\n", + "- Set up automated execution on Hetzner Cloud" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Step 1: Create Account & Choose Server\n", + "\n", + "### 1.1 Create Hetzner Account\n", + "1. Go to [hetzner.com](https://www.hetzner.com/)\n", + "2. Click \"Sign Up\" and create your account\n", + "3. Verify your email address\n", + "4. Add payment method (credit card or PayPal)\n", + "\n", + "### 1.2 Create Your Server\n", + "1. Log into Hetzner Cloud Console\n", + "2. Click \"New Project\" → Name it \"crypto-trading-bot\"\n", + "3. Click \"Add Server\"\n", + "4. **Choose Location**: Nuremberg or Helsinki (closest to major EU exchanges)\n", + "5. **Choose Image**: Ubuntu 22.04\n", + "6. **Choose Type**: CX11 (1 vCPU, 2GB RAM, 20GB storage) - €3.29/month\n", + "7. **SSH Key Setup**:\n", + " - If you have SSH key: Upload your public key\n", + " - If you don't: Select \"Password\" (we'll create SSH key later)\n", + "8. **Server Name**: \"trading-bot-server\"\n", + "9. Click \"Create & Buy Now\"\n", + "\n", + "**Your server will be ready in 30-60 seconds!**" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Step 2: Ubuntu Setup & SSH Access\n", + "\n", + "### 2.1 For Linux/Mac Users\n", + "\n", + "Replace `YOUR_SERVER_IP` with your actual server IP from Hetzner console:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "vscode": { + "languageId": "bat" + } + }, + "outputs": [], + "source": [ + "# Connect to your server (run in terminal, not Jupyter)\n", + "# If you used SSH key during setup:\n", + "ssh root@YOUR_SERVER_IP\n", + "\n", + "# If you used password:\n", + "ssh root@YOUR_SERVER_IP\n", + "# Enter the password from Hetzner console" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Create SSH Key (if you didn't have one)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "vscode": { + "languageId": "bat" + } + }, + "outputs": [], + "source": [ + "# On your local machine (run in terminal, not Jupyter):\n", + "ssh-keygen -t rsa -b 4096 -C \"your-email@example.com\"\n", + "# Press Enter for default location\n", + "# Press Enter for no passphrase (or set one if you prefer)\n", + "\n", + "# Copy your public key to server:\n", + "ssh-copy-id root@YOUR_SERVER_IP" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.2 For Windows Users\n", + "\n", + "#### Option A: Use Windows Terminal (Recommended)\n", + "1. Install Windows Terminal from Microsoft Store\n", + "2. Open Terminal and use same commands as Linux/Mac above\n", + "\n", + "#### Option B: Use PuTTY\n", + "1. Download PuTTY from [putty.org](https://www.putty.org/)\n", + "2. Open PuTTY\n", + "3. **Host Name**: YOUR_SERVER_IP\n", + "4. **Port**: 22\n", + "5. **Connection Type**: SSH\n", + "6. Click \"Open\"\n", + "7. Username: `root`\n", + "8. Password: (from Hetzner console)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "vscode": { + "languageId": "bat" + } + }, + "outputs": [], + "source": [ + "# Create SSH Key for Windows (run in Windows Terminal or PowerShell):\n", + "ssh-keygen -t rsa -b 4096 -C \"your-email@example.com\"\n", + "# Keys will be saved in C:\\Users\\YourName\\.ssh\\" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Step 3: Install Python & Dependencies\n", + "\n", + "**⚠️ Important: The following commands should be run on your Hetzner server (via SSH), not in this Jupyter notebook!**" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 3.1 Update System" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "vscode": { + "languageId": "bat" + } + }, + "outputs": [], + "source": [ + "# Update package list and upgrade system\n", + "sudo apt update && sudo apt upgrade -y" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 3.2 Install Python and Pip" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "vscode": { + "languageId": "bat" + } + }, + "outputs": [], + "source": [ + "# Install Python 3 and pip\n", + "sudo apt install python3 python3-pip python3-venv -y\n", + "\n", + "# Check installation\n", + "python3 --version\n", + "pip3 --version" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 3.3 Install Required Python Libraries" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "vscode": { + "languageId": "bat" + } + }, + "outputs": [], + "source": [ + "# Install common trading libraries\n", + "pip3 install pandas numpy ccxt python-dotenv requests\n", + "\n", + "# For backtesting (if using backtesting.py)\n", + "pip3 install backtesting\n", + "\n", + "# For notifications\n", + "pip3 install python-telegram-bot\n", + "\n", + "# Install any other libraries your bot uses" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 3.4 Install Screen (for running bot persistently)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "vscode": { + "languageId": "bat" + } + }, + "outputs": [], + "source": [ + "sudo apt install screen -y" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Step 4: Upload Your Bot Code\n", + "\n", + "### 4.1 Method 1: Using SCP (Secure Copy) - Linux/Mac" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "vscode": { + "languageId": "bat" + } + }, + "outputs": [], + "source": [ + "# From your local machine, copy your bot files (run in local terminal):\n", + "scp -r /path/to/your/bot/folder root@YOUR_SERVER_IP:/root/trading-bot/\n", + "\n", + "# Example:\n", + "scp -r ~/Desktop/my-crypto-bot root@YOUR_SERVER_IP:/root/trading-bot/" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 4.2 Method 1: Using SCP - Windows" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "vscode": { + "languageId": "bat" + } + }, + "outputs": [], + "source": [ + "# In Windows Terminal or PowerShell (run locally):\n", + "scp -r C:\\path\\to\\your\\bot\\folder root@YOUR_SERVER_IP:/root/trading-bot/\n", + "\n", + "# Example:\n", + "scp -r C:\\Users\\YourName\\Desktop\\my-crypto-bot root@YOUR_SERVER_IP:/root/trading-bot/" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 4.3 Method 2: Using Git (Recommended)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "vscode": { + "languageId": "bat" + } + }, + "outputs": [], + "source": [ + "# On your server:\n", + "cd /root/\n", + "git clone https://github.com/yourusername/your-trading-bot.git\n", + "cd your-trading-bot\n", + "\n", + "# Or if you don't have git repo, create directory and use nano:\n", + "mkdir trading-bot\n", + "cd trading-bot\n", + "nano main.py\n", + "# Paste your code, save with Ctrl+X, Y, Enter" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 4.4 Method 3: Using File Transfer (Windows PuTTY users)\n", + "1. Download WinSCP from [winscp.net](https://winscp.net/)\n", + "2. Connect using same credentials as PuTTY\n", + "3. Drag and drop your bot files to `/root/trading-bot/`" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Step 5: Configure Environment Variables\n", + "\n", + "### What are .env files?\n", + "\n", + "**Environment Variables & .env Files Explained**\n", + "\n", + "**What is a .env file?**\n", + "- A simple text file that stores configuration data\n", + "- Contains key-value pairs (API_KEY=your_secret_key)\n", + "- Kept separate from your main code\n", + "\n", + "**Why use .env files?**\n", + "- **Security**: Keeps secrets out of your code\n", + "- **Flexibility**: Easy to change settings without editing code\n", + "- **Version Control**: Never accidentally commit API keys to GitHub\n", + "- **Environment-specific**: Different keys for testing vs production" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 5.1 Create .env File" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "vscode": { + "languageId": "bat" + } + }, + "outputs": [], + "source": [ + "cd /root/trading-bot\n", + "nano .env" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 5.2 Add Your API Keys\n", + "\n", + "In the nano editor, add your keys:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "vscode": { + "languageId": "bat" + } + }, + "outputs": [], + "source": [ + "# Example .env file content:\n", + "BINANCE_API_KEY=your_actual_api_key_here\n", + "BINANCE_SECRET=your_actual_secret_key_here\n", + "\n", + "# Save: Ctrl+X, then Y, then Enter" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 5.3 Using .env in Your Python Code" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "from dotenv import load_dotenv\n", + "\n", + "# Load environment variables\n", + "load_dotenv()\n", + "\n", + "# Access your API keys\n", + "api_key = os.getenv('BINANCE_API_KEY')\n", + "secret_key = os.getenv('BINANCE_SECRET')\n", + "\n", + "print(f\"API Key loaded: {api_key[:10]}...\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 5.4 Secure Your .env File" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "vscode": { + "languageId": "bat" + } + }, + "outputs": [], + "source": [ + "# Make file readable only by owner\n", + "chmod 600 .env\n", + "\n", + "# Verify permissions\n", + "ls -la .env\n", + "# Should show: -rw------- 1 root root" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Step 6: Test Your Bot\n", + "\n", + "### 6.1 Run a Test" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "vscode": { + "languageId": "bat" + } + }, + "outputs": [], + "source": [ + "cd /root/trading-bot\n", + "python3 main.py" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 6.2 Run in Background with Screen" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "vscode": { + "languageId": "bat" + } + }, + "outputs": [], + "source": [ + "# Create a new screen session\n", + "screen -S trading-bot\n", + "\n", + "# Run your bot\n", + "python3 main.py\n", + "\n", + "# Detach from screen: Ctrl+A, then D\n", + "# Reattach later: screen -r trading-bot\n", + "# List screens: screen -ls" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Step 7: Set Up Automatic Restart (Optional)\n", + "\n", + "### 7.1 Create a Systemd Service" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "vscode": { + "languageId": "bat" + } + }, + "outputs": [], + "source": [ + "sudo nano /etc/systemd/system/trading-bot.service" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 7.2 Add Service Configuration\n", + "\n", + "Add this content to the service file:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "vscode": { + "languageId": "bat" + } + }, + "outputs": [], + "source": [ + "[Unit]\n", + "Description=Crypto Trading Bot\n", + "After=network.target\n", + "\n", + "[Service]\n", + "Type=simple\n", + "User=root\n", + "WorkingDirectory=/root/trading-bot\n", + "ExecStart=/usr/bin/python3 /root/trading-bot/main.py\n", + "Restart=always\n", + "RestartSec=10\n", + "\n", + "[Install]\n", + "WantedBy=multi-user.target" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 7.3 Enable and Start Service" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "vscode": { + "languageId": "bat" + } + }, + "outputs": [], + "source": [ + "# Reload systemd\n", + "sudo systemctl daemon-reload\n", + "\n", + "# Enable service (start on boot)\n", + "sudo systemctl enable trading-bot\n", + "\n", + "# Start service now\n", + "sudo systemctl start trading-bot\n", + "\n", + "# Check status\n", + "sudo systemctl status trading-bot\n", + "\n", + "# View logs\n", + "sudo journalctl -u trading-bot -f" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Common Commands Reference\n", + "\n", + "### Server Management" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "vscode": { + "languageId": "bat" + } + }, + "outputs": [], + "source": [ + "# Check running processes\n", + "ps aux | grep python\n", + "\n", + "# Kill a process\n", + "kill PID_NUMBER\n", + "\n", + "# Check system resources\n", + "htop\n", + "# (install with: sudo apt install htop)\n", + "\n", + "# Check disk space\n", + "df -h\n", + "\n", + "# Check memory usage\n", + "free -h" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Screen Commands" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "vscode": { + "languageId": "bat" + } + }, + "outputs": [], + "source": [ + "# Create new screen\n", + "screen -S session_name\n", + "\n", + "# List screens\n", + "screen -ls\n", + "\n", + "# Reattach to screen\n", + "screen -r session_name\n", + "\n", + "# Detach from screen\n", + "# Ctrl+A, then D\n", + "\n", + "# Kill screen session\n", + "screen -X -S session_name quit" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### File Operations" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "vscode": { + "languageId": "bat" + } + }, + "outputs": [], + "source": [ + "# View file contents\n", + "cat filename.py\n", + "\n", + "# Edit file\n", + "nano filename.py\n", + "\n", + "# Copy file\n", + "cp source.py backup.py\n", + "\n", + "# Move/rename file\n", + "mv oldname.py newname.py\n", + "\n", + "# Delete file\n", + "rm filename.py" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Troubleshooting\n", + "\n", + "### Connection Issues\n", + "- **Can't connect via SSH**: Check if server is running in Hetzner console\n", + "- **Permission denied**: Make sure you're using correct username (root) and IP\n", + "- **SSH key issues**: Try password authentication first\n", + "\n", + "### Python Issues\n", + "- **ModuleNotFoundError**: Install missing packages with `pip3 install package_name`\n", + "- **Permission errors**: Make sure you're in the correct directory\n", + "- **Python version issues**: Use `python3` instead of `python`\n", + "\n", + "### Bot Issues\n", + "- **API errors**: Double-check your .env file and API key permissions\n", + "- **Network errors**: Check internet connection with `ping google.com`\n", + "- **Log errors**: Check bot output for specific error messages" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Getting Help" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "vscode": { + "languageId": "bat" + } + }, + "outputs": [], + "source": [ + "# Check system logs\n", + "sudo journalctl -xe\n", + "\n", + "# Check your bot logs if using systemd\n", + "sudo journalctl -u trading-bot -f\n", + "\n", + "# Monitor system resources\n", + "htop" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 🎉 Congratulations!\n", + "\n", + "**Your trading bot is now running on Hetzner Cloud!**\n", + "\n", + "**Next Steps:**\n", + "- Monitor your bot's performance\n", + "- Set up alerts/notifications\n", + "- Consider adding more sophisticated error handling\n", + "- Scale up server resources if needed\n", + "\n", + "**Remember:**\n", + "- Start with small position sizes\n", + "- Test thoroughly before going live\n", + "- Always have kill switches ready\n", + "- Monitor your bot regularly" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "venv", + "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.13.3" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/Session_06/Notebooks/method_nohup.ipynb b/Session_06/Notebooks/method_nohup.ipynb new file mode 100644 index 0000000..c45a21f --- /dev/null +++ b/Session_06/Notebooks/method_nohup.ipynb @@ -0,0 +1,455 @@ +{ + "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 +} \ No newline at end of file diff --git a/Session_06/Notebooks/method_screen_tmux.ipynb b/Session_06/Notebooks/method_screen_tmux.ipynb new file mode 100644 index 0000000..eab4628 --- /dev/null +++ b/Session_06/Notebooks/method_screen_tmux.ipynb @@ -0,0 +1,636 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Running Your Trading Bot 24/7 with Screen/Tmux\n", + "\n", + "## Option 2: Screen & Tmux - Interactive Terminal Sessions\n", + "\n", + "**Best for:** Interactive monitoring, debugging, development\n", + "\n", + "**What Screen/Tmux do:**\n", + "- Create persistent terminal sessions that survive SSH disconnections\n", + "- Allow you to detach/reattach to running sessions\n", + "- Perfect for watching your bot's real-time output\n", + "- Great for debugging and development" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Part A: Using Screen\n", + "\n", + "### Step 1: Install Screen (if not already installed)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "# Install screen on Ubuntu/Debian\n", + "sudo apt update\n", + "sudo apt install screen -y\n", + "\n", + "# Check if screen is installed\n", + "screen --version" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Step 2: Basic Screen Usage" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "# Create a new screen session named 'trading-bot'\n", + "screen -S trading-bot\n", + "\n", + "# Inside the screen session, navigate to your bot directory\n", + "cd /root/trading-bot\n", + "\n", + "# Run your bot (you'll see live output)\n", + "python3 main.py" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Step 3: Screen Session Management" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "# Detach from screen session (bot keeps running)\n", + "# Press: Ctrl+A, then D\n", + "\n", + "# List all screen sessions\n", + "screen -ls\n", + "\n", + "# Reattach to your session\n", + "screen -r trading-bot\n", + "\n", + "# If only one session exists, just use:\n", + "screen -r\n", + "\n", + "# Force reattach if session is marked as attached\n", + "screen -d -r trading-bot" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Step 4: Advanced Screen Commands" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "# Create session with custom title\n", + "screen -S trading-bot -t \"Bot-Main\"\n", + "\n", + "# Create multiple windows in same session\n", + "# Inside screen:\n", + "# Ctrl+A, then C (create new window)\n", + "# Ctrl+A, then \" (list all windows)\n", + "# Ctrl+A, then 0-9 (switch to window number)\n", + "# Ctrl+A, then N (next window)\n", + "# Ctrl+A, then P (previous window)\n", + "\n", + "# Kill a screen session\n", + "screen -X -S trading-bot quit\n", + "\n", + "# Send command to screen session from outside\n", + "screen -S trading-bot -X stuff \"echo 'Bot status check'\\n\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Step 5: Screen Configuration (.screenrc)\n", + "\n", + "Create a custom screen configuration file:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "# Create screen configuration file\n", + "nano ~/.screenrc" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Contents of .screenrc:**" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "# Disable startup message\n", + "startup_message off\n", + "\n", + "# Set scrollback buffer\n", + "defscrollback 10000\n", + "\n", + "# Status line at bottom\n", + "hardstatus alwayslastline\n", + "hardstatus string '%{= kG}[%{G}%H%? %1`%?%{g}][%= %{= kw}%-w%{+b yk} %n*%t%?(%u)%? %{-}%+w %=%{g}][%{B}%m/%d %{W}%C%A%{g}]'\n", + "\n", + "# Enable mouse scrolling\n", + "termcapinfo xterm* ti@:te@\n", + "\n", + "# Auto-detach on hangup\n", + "autodetach on\n", + "\n", + "# Log output to file\n", + "deflog on\n", + "logfile /root/logs/screen-%Y%m%d-%n.log" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Part B: Using Tmux (Alternative to Screen)\n", + "\n", + "### Step 1: Install Tmux" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "# Install tmux on Ubuntu/Debian\n", + "sudo apt update\n", + "sudo apt install tmux -y\n", + "\n", + "# Check tmux version\n", + "tmux -V" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Step 2: Basic Tmux Usage" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "# Create a new tmux session named 'trading-bot'\n", + "tmux new-session -s trading-bot\n", + "\n", + "# Or shorter version:\n", + "tmux new -s trading-bot\n", + "\n", + "# Inside tmux session, run your bot\n", + "cd /root/trading-bot\n", + "python3 main.py" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Step 3: Tmux Session Management" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "# Detach from tmux session (bot keeps running)\n", + "# Press: Ctrl+B, then D\n", + "\n", + "# List all tmux sessions\n", + "tmux list-sessions\n", + "# or shorter:\n", + "tmux ls\n", + "\n", + "# Attach to session\n", + "tmux attach-session -t trading-bot\n", + "# or shorter:\n", + "tmux a -t trading-bot\n", + "\n", + "# Kill session\n", + "tmux kill-session -t trading-bot" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Step 4: Tmux Windows and Panes" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "# Inside tmux session:\n", + "\n", + "# Create new window: Ctrl+B, then C\n", + "# Switch windows: Ctrl+B, then 0-9\n", + "# Next window: Ctrl+B, then N\n", + "# Previous window: Ctrl+B, then P\n", + "# List windows: Ctrl+B, then W\n", + "\n", + "# Split panes:\n", + "# Horizontal split: Ctrl+B, then \"\n", + "# Vertical split: Ctrl+B, then %\n", + "# Switch panes: Ctrl+B, then arrow keys\n", + "# Close pane: Ctrl+B, then X" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Step 5: Advanced Tmux Setup for Trading Bot" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "# Create a comprehensive trading bot session\n", + "tmux new-session -d -s trading-bot -n main\n", + "tmux send-keys -t trading-bot:main \"cd /root/trading-bot\" Enter\n", + "tmux send-keys -t trading-bot:main \"python3 main.py\" Enter\n", + "\n", + "# Create additional windows for monitoring\n", + "tmux new-window -t trading-bot -n logs\n", + "tmux send-keys -t trading-bot:logs \"cd /root/trading-bot && tail -f bot.log\" Enter\n", + "\n", + "tmux new-window -t trading-bot -n system\n", + "tmux send-keys -t trading-bot:system \"htop\" Enter\n", + "\n", + "# Attach to the session\n", + "tmux attach-session -t trading-bot" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Step 6: Create Automated Setup Script" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "# Create setup script\n", + "nano setup_trading_session.sh" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Contents of setup_trading_session.sh:**" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "#!/bin/bash\n", + "\n", + "SESSION_NAME=\"trading-bot\"\n", + "BOT_DIR=\"/root/trading-bot\"\n", + "\n", + "# Check if session already exists\n", + "tmux has-session -t $SESSION_NAME 2>/dev/null\n", + "if [ $? == 0 ]; then\n", + " echo \"Session $SESSION_NAME already exists. Attaching...\"\n", + " tmux attach-session -t $SESSION_NAME\n", + " exit 0\n", + "fi\n", + "\n", + "echo \"Creating new trading bot session...\"\n", + "\n", + "# Create new session with main window\n", + "tmux new-session -d -s $SESSION_NAME -n \"bot\"\n", + "tmux send-keys -t $SESSION_NAME:bot \"cd $BOT_DIR\" Enter\n", + "tmux send-keys -t $SESSION_NAME:bot \"echo 'Starting trading bot...'\" Enter\n", + "tmux send-keys -t $SESSION_NAME:bot \"python3 main.py\" Enter\n", + "\n", + "# Create logs window\n", + "tmux new-window -t $SESSION_NAME -n \"logs\"\n", + "tmux send-keys -t $SESSION_NAME:logs \"cd $BOT_DIR\" Enter\n", + "tmux send-keys -t $SESSION_NAME:logs \"tail -f *.log\" Enter\n", + "\n", + "# Create monitoring window with split panes\n", + "tmux new-window -t $SESSION_NAME -n \"monitor\"\n", + "tmux send-keys -t $SESSION_NAME:monitor \"htop\" Enter\n", + "tmux split-window -v -t $SESSION_NAME:monitor\n", + "tmux send-keys -t $SESSION_NAME:monitor \"watch -n 5 'df -h'\" Enter\n", + "\n", + "# Create development window\n", + "tmux new-window -t $SESSION_NAME -n \"dev\"\n", + "tmux send-keys -t $SESSION_NAME:dev \"cd $BOT_DIR\" Enter\n", + "\n", + "# Select the main bot window\n", + "tmux select-window -t $SESSION_NAME:bot\n", + "\n", + "echo \"Trading bot session created. Attaching...\"\n", + "tmux attach-session -t $SESSION_NAME" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "# Make script executable\n", + "chmod +x setup_trading_session.sh\n", + "\n", + "# Run the setup script\n", + "./setup_trading_session.sh" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Part C: Comparison - Screen vs Tmux\n", + "\n", + "### Screen\n", + "**Pros:**\n", + "- Simpler syntax and commands\n", + "- Lightweight and fast\n", + "- Available on almost all Unix systems\n", + "- Good for basic use cases\n", + "\n", + "**Cons:**\n", + "- Limited customization\n", + "- No pane splitting\n", + "- Less intuitive key bindings\n", + "\n", + "### Tmux\n", + "**Pros:**\n", + "- More powerful and flexible\n", + "- Better pane and window management\n", + "- Highly customizable\n", + "- Better mouse support\n", + "- More active development\n", + "\n", + "**Cons:**\n", + "- Steeper learning curve\n", + "- More complex configuration\n", + "- Might not be installed by default" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Part D: Best Practices for Trading Bots\n", + "\n", + "### 1. Multiple Windows Setup" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "# Window 1: Main bot execution\n", + "# Window 2: Log monitoring (tail -f logs)\n", + "# Window 3: System monitoring (htop, df -h)\n", + "# Window 4: Development/debugging\n", + "# Window 5: Market data (if applicable)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2. Session Persistence" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "# For tmux - save and restore sessions\n", + "# Install tmux-resurrect plugin\n", + "git clone https://github.com/tmux-plugins/tmux-resurrect ~/.tmux/plugins/tmux-resurrect\n", + "\n", + "# Add to ~/.tmux.conf:\n", + "# run-shell ~/.tmux/plugins/tmux-resurrect/resurrect.tmux\n", + "\n", + "# Save session: Ctrl+B, then Ctrl+S\n", + "# Restore session: Ctrl+B, then Ctrl+R" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 3. Logging Within Sessions" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "# Enable logging in screen\n", + "# Inside screen session: Ctrl+A, then H\n", + "\n", + "# Enable logging in tmux\n", + "# Add to ~/.tmux.conf:\n", + "# set -g history-limit 50000\n", + "# bind-key S capture-pane -p > ~/tmux-session.log" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Part E: Monitoring and Troubleshooting\n", + "\n", + "### Quick Status Checks" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "# Check if your session is running\n", + "screen -ls | grep trading-bot\n", + "# or\n", + "tmux ls | grep trading-bot\n", + "\n", + "# Quick attach without typing session name\n", + "# If only one session exists:\n", + "screen -r\n", + "# or\n", + "tmux a\n", + "\n", + "# Check processes inside session\n", + "ps aux | grep python3" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Emergency Recovery" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "# If session appears stuck or unresponsive:\n", + "\n", + "# Force detach and reattach\n", + "screen -d trading-bot\n", + "screen -r trading-bot\n", + "\n", + "# Or for tmux:\n", + "tmux detach-client -s trading-bot\n", + "tmux a -t trading-bot\n", + "\n", + "# If session is completely broken, kill and restart:\n", + "screen -X -S trading-bot quit\n", + "# or\n", + "tmux kill-session -t trading-bot" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Part F: Integration with Other Tools\n", + "\n", + "### Combining with Systemd" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "# Create a systemd service that starts a tmux session\n", + "sudo nano /etc/systemd/system/trading-bot-tmux.service" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Service file content:**" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "[Unit]\n", + "Description=Trading Bot Tmux Session\n", + "After=network.target\n", + "\n", + "[Service]\n", + "Type=forking\n", + "User=root\n", + "ExecStart=/usr/bin/tmux new-session -d -s trading-bot -c /root/trading-bot 'python3 main.py'\n", + "ExecStop=/usr/bin/tmux kill-session -t trading-bot\n", + "Restart=on-failure\n", + "RestartSec=10\n", + "\n", + "[Install]\n", + "WantedBy=multi-user.target" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Pros and Cons Summary\n", + "\n", + "### ✅ Pros:\n", + "- **Interactive monitoring** - see real-time output\n", + "- **Easy debugging** - can interact with running bot\n", + "- **Session persistence** - survives SSH disconnections\n", + "- **Multiple windows** - organize different views\n", + "- **Flexible** - can run any commands in sessions\n", + "- **No additional setup** - works out of the box\n", + "\n", + "### ❌ Cons:\n", + "- **No automatic restart** on crash\n", + "- **Manual session management** - need to remember to detach\n", + "- **Resource usage** - sessions consume memory\n", + "- **Lost on reboot** - sessions don't survive server restart\n", + "- **Learning curve** - need to memorize key combinations\n", + "\n", + "### 🎯 Best Use Cases:\n", + "- Development and testing phase\n", + "- Active monitoring and debugging\n", + "- When you need to interact with the bot frequently\n", + "- Learning how your bot behaves\n", + "- Running multiple related processes" + ] + } + ], + "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 +} \ No newline at end of file diff --git a/Session_06/Notebooks/method_ssytemd.ipynb b/Session_06/Notebooks/method_ssytemd.ipynb new file mode 100644 index 0000000..3218af3 --- /dev/null +++ b/Session_06/Notebooks/method_ssytemd.ipynb @@ -0,0 +1,1117 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Running Your Trading Bot 24/7 with Systemd\n", + "\n", + "## Option 3: Systemd Services - Production-Ready Deployment\n", + "\n", + "**Best for:** Production environments, automatic restarts, professional deployments\n", + "\n", + "**What Systemd does:**\n", + "- Manages your bot as a proper Linux service\n", + "- Automatically starts on system boot\n", + "- Restarts your bot if it crashes\n", + "- Provides structured logging\n", + "- Allows easy start/stop/restart operations\n", + "- Professional service management" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Step 1: Understanding Systemd\n", + "\n", + "### What is Systemd?\n", + "- **Service manager** for Linux systems\n", + "- **Handles** starting, stopping, and monitoring services\n", + "- **Manages dependencies** between services\n", + "- **Provides logging** through journald\n", + "- **Standard** on modern Linux distributions" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Step 2: Create Your First Service File\n", + "\n", + "### 2.1 Basic Service File" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "# Create the service file\n", + "sudo nano /etc/systemd/system/trading-bot.service" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Basic service file content:**" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "[Unit]\n", + "Description=Crypto Trading Bot\n", + "After=network.target\n", + "\n", + "[Service]\n", + "Type=simple\n", + "User=root\n", + "WorkingDirectory=/root/trading-bot\n", + "ExecStart=/usr/bin/python3 /root/trading-bot/main.py\n", + "Restart=always\n", + "RestartSec=10\n", + "\n", + "[Install]\n", + "WantedBy=multi-user.target" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.2 Enable and Start the Service" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "# Reload systemd to recognize new service\n", + "sudo systemctl daemon-reload\n", + "\n", + "# Enable service (start automatically on boot)\n", + "sudo systemctl enable trading-bot\n", + "\n", + "# Start the service now\n", + "sudo systemctl start trading-bot\n", + "\n", + "# Check service status\n", + "sudo systemctl status trading-bot" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Step 3: Service Management Commands" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "# Start service\n", + "sudo systemctl start trading-bot\n", + "\n", + "# Stop service\n", + "sudo systemctl stop trading-bot\n", + "\n", + "# Restart service\n", + "sudo systemctl restart trading-bot\n", + "\n", + "# Reload service configuration\n", + "sudo systemctl reload trading-bot\n", + "\n", + "# Check service status\n", + "sudo systemctl status trading-bot\n", + "\n", + "# Enable auto-start on boot\n", + "sudo systemctl enable trading-bot\n", + "\n", + "# Disable auto-start on boot\n", + "sudo systemctl disable trading-bot\n", + "\n", + "# Check if service is enabled\n", + "sudo systemctl is-enabled trading-bot\n", + "\n", + "# Check if service is active\n", + "sudo systemctl is-active trading-bot" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Step 4: Advanced Service Configuration\n", + "\n", + "### 4.1 Enhanced Service File with Environment Variables" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "# Create enhanced service file\n", + "sudo nano /etc/systemd/system/trading-bot-advanced.service" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Advanced service file content:**" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "[Unit]\n", + "Description=Advanced Crypto Trading Bot\n", + "Documentation=https://your-docs.com\n", + "After=network-online.target\n", + "Wants=network-online.target\n", + "RequiresMountsFor=/root/trading-bot\n", + "\n", + "[Service]\n", + "Type=simple\n", + "User=root\n", + "Group=root\n", + "WorkingDirectory=/root/trading-bot\n", + "\n", + "# Environment variables\n", + "Environment=PYTHONPATH=/root/trading-bot\n", + "Environment=PYTHON_ENV=production\n", + "EnvironmentFile=-/root/trading-bot/.env\n", + "\n", + "# Main execution\n", + "ExecStartPre=/bin/mkdir -p /var/log/trading-bot\n", + "ExecStart=/usr/bin/python3 /root/trading-bot/main.py\n", + "ExecReload=/bin/kill -HUP $MAINPID\n", + "ExecStop=/bin/kill -TERM $MAINPID\n", + "\n", + "# Restart configuration\n", + "Restart=always\n", + "RestartSec=10\n", + "StartLimitInterval=60\n", + "StartLimitBurst=3\n", + "\n", + "# Security settings\n", + "NoNewPrivileges=yes\n", + "PrivateTmp=yes\n", + "ProtectSystem=strict\n", + "ProtectHome=yes\n", + "ReadWritePaths=/root/trading-bot /var/log/trading-bot\n", + "\n", + "# Resource limits\n", + "LimitNOFILE=65536\n", + "MemoryHigh=512M\n", + "MemoryMax=1G\n", + "\n", + "# Logging\n", + "StandardOutput=journal\n", + "StandardError=journal\n", + "SyslogIdentifier=trading-bot\n", + "\n", + "[Install]\n", + "WantedBy=multi-user.target" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 4.2 Service File Sections Explained\n", + "\n", + "#### [Unit] Section\n", + "- **Description**: Human-readable description\n", + "- **After**: Start after these services\n", + "- **Wants**: Weak dependency (nice to have)\n", + "- **Requires**: Strong dependency (must have)\n", + "\n", + "#### [Service] Section\n", + "- **Type**: How systemd should manage the process\n", + "- **User/Group**: Which user runs the service\n", + "- **WorkingDirectory**: Where to run the command\n", + "- **ExecStart**: Main command to run\n", + "- **Restart**: When to restart (always, on-failure, etc.)\n", + "\n", + "#### [Install] Section\n", + "- **WantedBy**: Which target should include this service" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Step 5: Service Types and Restart Policies\n", + "\n", + "### 5.1 Service Types" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "# Type=simple (default)\n", + "# Systemd considers service started immediately\n", + "Type=simple\n", + "\n", + "# Type=forking\n", + "# Service forks and parent exits\n", + "Type=forking\n", + "PIDFile=/var/run/trading-bot.pid\n", + "\n", + "# Type=oneshot\n", + "# Service runs once and exits\n", + "Type=oneshot\n", + "RemainAfterExit=yes\n", + "\n", + "# Type=notify\n", + "# Service sends readiness notification\n", + "Type=notify\n", + "NotifyAccess=main" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 5.2 Restart Policies" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "# Restart=always (recommended for trading bots)\n", + "# Always restart, regardless of exit status\n", + "Restart=always\n", + "\n", + "# Restart=on-failure\n", + "# Restart only on failure (non-zero exit)\n", + "Restart=on-failure\n", + "\n", + "# Restart=on-abnormal\n", + "# Restart on abnormal exit (signals, timeouts)\n", + "Restart=on-abnormal\n", + "\n", + "# Restart=on-abort\n", + "# Restart only on abort signals\n", + "Restart=on-abort\n", + "\n", + "# Additional restart settings\n", + "RestartSec=10 # Wait 10 seconds before restart\n", + "StartLimitBurst=3 # Max 3 restarts\n", + "StartLimitInterval=60 # Within 60 seconds" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Step 6: Logging and Monitoring\n", + "\n", + "### 6.1 Viewing Service Logs" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "# View recent logs\n", + "sudo journalctl -u trading-bot\n", + "\n", + "# Follow logs in real-time\n", + "sudo journalctl -u trading-bot -f\n", + "\n", + "# View logs from today\n", + "sudo journalctl -u trading-bot --since today\n", + "\n", + "# View logs from specific time\n", + "sudo journalctl -u trading-bot --since \"2024-01-01 00:00:00\"\n", + "\n", + "# View last 100 lines\n", + "sudo journalctl -u trading-bot -n 100\n", + "\n", + "# View logs with priority (error, warning, info)\n", + "sudo journalctl -u trading-bot -p err\n", + "\n", + "# Export logs to file\n", + "sudo journalctl -u trading-bot > /tmp/trading-bot.log" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 6.2 Log Configuration" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "# Configure journal log retention\n", + "sudo nano /etc/systemd/journald.conf" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Add to journald.conf:**" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "[Journal]\n", + "# Keep logs for 30 days\n", + "MaxRetentionSec=30d\n", + "# Limit journal size to 1GB\n", + "SystemMaxUse=1G\n", + "# Limit individual log files to 100MB\n", + "SystemMaxFileSize=100M" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Step 7: Multiple Bot Services\n", + "\n", + "### 7.1 Template Service Files" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "# Create template service\n", + "sudo nano /etc/systemd/system/trading-bot@.service" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Template service content:**" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "[Unit]\n", + "Description=Trading Bot - %i\n", + "After=network.target\n", + "\n", + "[Service]\n", + "Type=simple\n", + "User=root\n", + "WorkingDirectory=/root/trading-bots/%i\n", + "ExecStart=/usr/bin/python3 /root/trading-bots/%i/main.py\n", + "Restart=always\n", + "RestartSec=10\n", + "Environment=BOT_NAME=%i\n", + "\n", + "[Install]\n", + "WantedBy=multi-user.target" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 7.2 Managing Multiple Bots" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "# Create bot directories\n", + "mkdir -p /root/trading-bots/{btc-bot,eth-bot,doge-bot}\n", + "\n", + "# Start specific bot instances\n", + "sudo systemctl start trading-bot@btc-bot\n", + "sudo systemctl start trading-bot@eth-bot\n", + "sudo systemctl start trading-bot@doge-bot\n", + "\n", + "# Enable auto-start for specific bots\n", + "sudo systemctl enable trading-bot@btc-bot\n", + "sudo systemctl enable trading-bot@eth-bot\n", + "\n", + "# Check status of all bot instances\n", + "sudo systemctl status 'trading-bot@*'\n", + "\n", + "# View logs for specific bot\n", + "sudo journalctl -u trading-bot@btc-bot -f" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Step 8: Service Dependencies and Ordering\n", + "\n", + "### 8.1 Creating Dependencies" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "# Example: Trading bot that depends on database\n", + "sudo nano /etc/systemd/system/trading-bot-with-deps.service" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Service with dependencies:**" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "[Unit]\n", + "Description=Trading Bot with Database Dependency\n", + "After=network-online.target postgresql.service\n", + "Wants=network-online.target\n", + "Requires=postgresql.service\n", + "BindsTo=postgresql.service\n", + "\n", + "[Service]\n", + "Type=simple\n", + "User=root\n", + "WorkingDirectory=/root/trading-bot\n", + "ExecStart=/usr/bin/python3 /root/trading-bot/main.py\n", + "Restart=always\n", + "RestartSec=10\n", + "\n", + "# Stop if database stops\n", + "PartOf=postgresql.service\n", + "\n", + "[Install]\n", + "WantedBy=multi-user.target" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Step 9: Health Checks and Monitoring\n", + "\n", + "### 9.1 Service with Health Checks" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "# Create health check script\n", + "nano /root/trading-bot/health_check.py" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Health check script:**" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "#!/usr/bin/env python3\n", + "import sys\n", + "import os\n", + "import time\n", + "from datetime import datetime, timedelta\n", + "\n", + "def check_bot_health():\n", + " \"\"\"Check if bot is healthy\"\"\"\n", + " \n", + " # Check if heartbeat file exists and is recent\n", + " heartbeat_file = '/tmp/trading-bot-heartbeat'\n", + " \n", + " if not os.path.exists(heartbeat_file):\n", + " print(\"ERROR: Heartbeat file not found\")\n", + " return False\n", + " \n", + " # Check if heartbeat is recent (within last 5 minutes)\n", + " file_time = datetime.fromtimestamp(os.path.getmtime(heartbeat_file))\n", + " if datetime.now() - file_time > timedelta(minutes=5):\n", + " print(\"ERROR: Heartbeat file is too old\")\n", + " return False\n", + " \n", + " # Check log file for errors\n", + " log_file = '/root/trading-bot/bot.log'\n", + " if os.path.exists(log_file):\n", + " with open(log_file, 'r') as f:\n", + " lines = f.readlines()[-10:] # Last 10 lines\n", + " for line in lines:\n", + " if 'CRITICAL' in line or 'FATAL' in line:\n", + " print(\"ERROR: Critical error found in logs\")\n", + " return False\n", + " \n", + " print(\"OK: Bot is healthy\")\n", + " return True\n", + "\n", + "if __name__ == \"__main__\":\n", + " if check_bot_health():\n", + " sys.exit(0)\n", + " else:\n", + " sys.exit(1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 9.2 Service with Health Monitoring" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "# Create service with health checks\n", + "sudo nano /etc/systemd/system/trading-bot-monitored.service" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Service with monitoring:**" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "[Unit]\n", + "Description=Monitored Trading Bot\n", + "After=network.target\n", + "\n", + "[Service]\n", + "Type=simple\n", + "User=root\n", + "WorkingDirectory=/root/trading-bot\n", + "ExecStart=/usr/bin/python3 /root/trading-bot/main.py\n", + "ExecStartPost=/bin/sleep 30\n", + "ExecReload=/root/trading-bot/health_check.py\n", + "\n", + "# Health monitoring\n", + "Restart=always\n", + "RestartSec=10\n", + "WatchdogSec=300\n", + "NotifyAccess=all\n", + "\n", + "# Failure detection\n", + "StartLimitBurst=5\n", + "StartLimitInterval=300\n", + "\n", + "[Install]\n", + "WantedBy=multi-user.target" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Step 10: Notification and Alerting\n", + "\n", + "### 10.1 Email Alerts on Failure" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "# Create alert script\n", + "nano /root/scripts/trading-bot-alert.sh" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Alert script:**" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "#!/bin/bash\n", + "\n", + "SERVICE=$1\n", + "STATUS=$2\n", + "TIMESTAMP=$(date)\n", + "HOSTNAME=$(hostname)\n", + "\n", + "# Email configuration\n", + "TO_EMAIL=\"your-email@example.com\"\n", + "SUBJECT=\"Trading Bot Alert: $SERVICE $STATUS\"\n", + "\n", + "# Create email body\n", + "EMAIL_BODY=\"\n", + "Trading Bot Alert\n", + "================\n", + "\n", + "Service: $SERVICE\n", + "Status: $STATUS\n", + "Timestamp: $TIMESTAMP\n", + "Hostname: $HOSTNAME\n", + "\n", + "Recent logs:\n", + "$(sudo journalctl -u $SERVICE -n 20 --no-pager)\n", + "\n", + "System status:\n", + "$(df -h)\n", + "$(free -h)\n", + "\"\n", + "\n", + "# Send email (requires mail command)\n", + "echo \"$EMAIL_BODY\" | mail -s \"$SUBJECT\" \"$TO_EMAIL\"\n", + "\n", + "# Send Telegram notification (optional)\n", + "if [ ! -z \"$TELEGRAM_BOT_TOKEN\" ] && [ ! -z \"$TELEGRAM_CHAT_ID\" ]; then\n", + " curl -s -X POST \"https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/sendMessage\" \\\n", + " -d chat_id=\"$TELEGRAM_CHAT_ID\" \\\n", + " -d text=\"🚨 Trading Bot Alert: $SERVICE $STATUS on $HOSTNAME at $TIMESTAMP\"\n", + "fi" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 10.2 Service with Failure Notifications" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "# Create service with failure hooks\n", + "sudo nano /etc/systemd/system/trading-bot-alerts.service" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Service with alerts:**" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "[Unit]\n", + "Description=Trading Bot with Alerts\n", + "After=network.target\n", + "OnFailure=trading-bot-failure@%n.service\n", + "\n", + "[Service]\n", + "Type=simple\n", + "User=root\n", + "WorkingDirectory=/root/trading-bot\n", + "ExecStart=/usr/bin/python3 /root/trading-bot/main.py\n", + "ExecStartPost=/root/scripts/trading-bot-alert.sh %n started\n", + "ExecStopPost=/root/scripts/trading-bot-alert.sh %n stopped\n", + "Restart=always\n", + "RestartSec=10\n", + "\n", + "[Install]\n", + "WantedBy=multi-user.target" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 10.3 Failure Handler Service" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "# Create failure handler\n", + "sudo nano /etc/systemd/system/trading-bot-failure@.service" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Failure handler service:**" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "[Unit]\n", + "Description=Trading Bot Failure Handler for %i\n", + "\n", + "[Service]\n", + "Type=oneshot\n", + "ExecStart=/root/scripts/trading-bot-alert.sh %i failed\n", + "User=root" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Step 11: Backup and Recovery\n", + "\n", + "### 11.1 Service State Backup" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "# Create backup script\n", + "nano /root/scripts/backup-trading-bot.sh" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Backup script:**" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "#!/bin/bash\n", + "\n", + "BACKUP_DIR=\"/root/backups/$(date +%Y%m%d_%H%M%S)\"\n", + "BOT_DIR=\"/root/trading-bot\"\n", + "\n", + "# Create backup directory\n", + "mkdir -p \"$BACKUP_DIR\"\n", + "\n", + "# Stop service\n", + "sudo systemctl stop trading-bot\n", + "\n", + "# Backup files\n", + "cp -r \"$BOT_DIR\" \"$BACKUP_DIR/\"\n", + "cp /etc/systemd/system/trading-bot*.service \"$BACKUP_DIR/\"\n", + "\n", + "# Backup service status\n", + "sudo systemctl status trading-bot > \"$BACKUP_DIR/service-status.txt\"\n", + "sudo journalctl -u trading-bot -n 1000 > \"$BACKUP_DIR/recent-logs.txt\"\n", + "\n", + "# Start service\n", + "sudo systemctl start trading-bot\n", + "\n", + "echo \"Backup completed: $BACKUP_DIR\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 11.2 Automated Backup Service" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "# Create backup service\n", + "sudo nano /etc/systemd/system/trading-bot-backup.service" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Backup service:**" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "[Unit]\n", + "Description=Trading Bot Backup\n", + "Requires=trading-bot.service\n", + "\n", + "[Service]\n", + "Type=oneshot\n", + "ExecStart=/root/scripts/backup-trading-bot.sh\n", + "User=root" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 11.3 Backup Timer" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "# Create backup timer\n", + "sudo nano /etc/systemd/system/trading-bot-backup.timer" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Backup timer:**" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "[Unit]\n", + "Description=Trading Bot Daily Backup\n", + "Requires=trading-bot-backup.service\n", + "\n", + "[Timer]\n", + "OnCalendar=daily\n", + "Persistent=true\n", + "\n", + "[Install]\n", + "WantedBy=timers.target" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "# Enable and start backup timer\n", + "sudo systemctl enable trading-bot-backup.timer\n", + "sudo systemctl start trading-bot-backup.timer\n", + "\n", + "# Check timer status\n", + "sudo systemctl status trading-bot-backup.timer\n", + "\n", + "# List all timers\n", + "sudo systemctl list-timers" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Step 12: Troubleshooting and Debugging\n", + "\n", + "### 12.1 Common Issues" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "# Service won't start\n", + "sudo systemctl status trading-bot\n", + "sudo journalctl -u trading-bot -n 50\n", + "\n", + "# Check service file syntax\n", + "sudo systemd-analyze verify /etc/systemd/system/trading-bot.service\n", + "\n", + "# Service starts but immediately fails\n", + "sudo journalctl -u trading-bot --since \"5 minutes ago\"\n", + "\n", + "# Permission issues\n", + "sudo ls -la /root/trading-bot/\n", + "sudo chmod +x /root/trading-bot/main.py\n", + "\n", + "# Environment variable issues\n", + "sudo systemctl show trading-bot --property=Environment\n", + "\n", + "# Service dependency issues\n", + "sudo systemctl list-dependencies trading-bot" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 12.2 Debug Mode Service" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "# Create debug version of service\n", + "sudo nano /etc/systemd/system/trading-bot-debug.service" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Debug service:**" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "[Unit]\n", + "Description=Trading Bot (Debug Mode)\n", + "After=network.target\n", + "\n", + "[Service]\n", + "Type=simple\n", + "User=root\n", + "WorkingDirectory=/root/trading-bot\n", + "ExecStart=/usr/bin/python3 -u -v /root/trading-bot/main.py\n", + "Environment=PYTHONUNBUFFERED=1\n", + "Environment=DEBUG=1\n", + "StandardOutput=journal+console\n", + "StandardError=journal+console\n", + "Restart=no\n", + "\n", + "[Install]\n", + "WantedBy=multi-user.target" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Step 13: Performance Monitoring\n", + "\n", + "### 13.1 Resource Usage Monitoring" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "source": [ + "# Show service resource usage\n", + "sudo systemctl status trading-bot\n", + "\n", + "# Detailed resource usage\n", + "sudo systemd-cgtop\n", + "\n", + "# Memory usage of service\n", + "sudo systemctl show trading-bot --property=MemoryCurrent\n", + "\n", + "# CPU usage\n", + "sudo systemctl show trading-bot --property=CPUUsageNSec\n", + "\n", + "# All service properties\n", + "sudo systemctl show trading-bot" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Pros and Cons Summary\n", + "\n", + "### ✅ Pros:\n", + "- **Professional deployment** - industry standard approach\n", + "- **Automatic restart** on crash or system reboot\n", + "- **Structured logging** - integrated with system logs\n", + "- **Resource management** - memory and CPU limits\n", + "- **Dependency management** - service ordering and requirements\n", + "- **Security features** - sandboxing and privilege restrictions\n", + "- **Monitoring integration** - works with system monitoring tools\n", + "- **Scalable** - easy to manage multiple services\n", + "\n", + "### ❌ Cons:\n", + "- **Complex setup** - requires understanding of systemd\n", + "- **Learning curve** - many configuration options\n", + "- **Root access required** - need sudo for service management\n", + "- **Less interactive** - harder to debug running processes\n", + "- **System-specific** - tied to systemd-based Linux distributions\n", + "\n", + "### 🎯 Best Use Cases:\n", + "- Production trading bot deployments\n", + "- Multiple trading strategies running simultaneously\n", + "- When you need reliable 24/7 operation\n", + "- Professional or commercial trading operations\n", + "- When automatic restart and monitoring are critical\n", + "- Server environments with multiple services" + ] + } + ], + "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 +} \ No newline at end of file diff --git a/Session_06/_files_ b/Session_06/_files_ deleted file mode 100644 index e69de29..0000000 diff --git a/Session_06/algorithm-service.sh b/Session_06/algorithm-service.sh new file mode 100755 index 0000000..ece2f58 --- /dev/null +++ b/Session_06/algorithm-service.sh @@ -0,0 +1,170 @@ +#!/bin/bash +# VAMR Algorithm Service Script +# Usage: ./algorithm-service.sh {start|stop|restart|status} + +# Get the script directory +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +# Navigate to the root directory (2 levels up from the script directory) +ROOT_DIR="$(cd "$SCRIPT_DIR/../.." && pwd)" + +# Define paths +PYTHON_PATH="$ROOT_DIR/venv/bin/python" +ALGORITHM_PATH="$ROOT_DIR/VAMR/VAMR/algorithm.py" +LOG_DIR="$ROOT_DIR/VAMR/logs" +LOG_ARCHIVE_DIR="$LOG_DIR/archive" +DATA_DIR="$ROOT_DIR/VAMR/data" +PID_FILE="$DATA_DIR/algorithm.pid" +STDOUT_LOG="$LOG_DIR/stdout.log" +ERROR_LOG="$LOG_DIR/error.log" +INFO_LOG="$LOG_DIR/info.log" + +# Ensure directories exist +mkdir -p "$LOG_DIR" +mkdir -p "$LOG_ARCHIVE_DIR" +mkdir -p "$DATA_DIR" + +# Function to start the algorithm +start_algorithm() { + echo "Starting VAMR trading algorithm..." + if [ -f "$PID_FILE" ]; then + PID=$(cat "$PID_FILE") + if ps -p $PID > /dev/null; then + echo "Algorithm is already running with PID: $PID" + return 1 + else + echo "Removing stale PID file" + rm "$PID_FILE" + fi + fi + + # Rotate log files: Move existing logs to archive with timestamp + if [ -f "$INFO_LOG" ]; then + TIMESTAMP=$(date +"%Y%m%d_%H%M%S") + echo "Archiving existing info.log to archive folder with timestamp $TIMESTAMP" + mv "$INFO_LOG" "$LOG_ARCHIVE_DIR/info_$TIMESTAMP.log" + fi + + # Create empty logs + touch "$INFO_LOG" + + # Change to root directory and activate virtual environment + cd "$ROOT_DIR" + source venv/bin/activate + + # Start algorithm in the background + cd VAMR/VAMR + nohup python algorithm.py > "$STDOUT_LOG" 2> "$ERROR_LOG" & disown + + # Save PID for later use + echo $! > "$PID_FILE" + echo "Algorithm started with PID: $(cat "$PID_FILE")" + return 0 +} + +# Function to stop the algorithm +stop_algorithm() { + echo "Stopping VAMR trading algorithm..." + if [ -f "$PID_FILE" ]; then + PID=$(cat "$PID_FILE") + if ps -p $PID > /dev/null; then + echo "Stopping algorithm with PID: $PID" + kill $PID + sleep 2 + + # Check if process is still running + if ps -p $PID > /dev/null; then + echo "Algorithm still running, forcing termination..." + kill -9 $PID + sleep 1 + fi + + # Verify process is stopped + if ps -p $PID > /dev/null; then + echo "ERROR: Failed to stop algorithm!" + return 1 + else + echo "Algorithm stopped successfully." + rm "$PID_FILE" + return 0 + fi + else + echo "No algorithm running with PID: $PID (stale PID file)" + rm "$PID_FILE" + return 0 + fi + else + echo "No PID file found. Algorithm may not be running." + return 0 + fi +} + +# Function to check algorithm status +status_algorithm() { + echo "===== VAMR Trading Algorithm Status =====" + + # Check if algorithm is running + if [ -f "$PID_FILE" ]; then + PID=$(cat "$PID_FILE") + if ps -p $PID > /dev/null; then + echo "Status: RUNNING" + echo "PID: $PID" + + # Get runtime information + PROC_START=$(ps -p $PID -o lstart=) + echo "Running since: $PROC_START" + + # Get memory usage + MEM_USAGE=$(ps -p $PID -o %mem=) + echo "Memory usage: $MEM_USAGE%" + + # Check state file + STATE_FILE="$DATA_DIR/state.json" + if [ -f "$STATE_FILE" ]; then + STATE_SIZE=$(du -h "$STATE_FILE" | cut -f1) + STATE_TIME=$(date -r "$STATE_FILE" "+%Y-%m-%d %H:%M:%S") + echo "State file: $STATE_SIZE, last updated: $STATE_TIME" + else + echo "State file: NOT FOUND" + fi + + # Show recent log entries + echo "" + echo "Recent log entries:" + echo "--- Last 5 lines of algorithm log ---" + tail -n 5 "$INFO_LOG" + return 0 + else + echo "Status: NOT RUNNING (stale PID file)" + rm "$PID_FILE" + return 1 + fi + else + echo "Status: NOT RUNNING (no PID file)" + return 1 + fi +} + +# Main logic +case "$1" in + start) + start_algorithm + ;; + stop) + stop_algorithm + ;; + restart) + stop_algorithm + sleep 2 + start_algorithm + ;; + status) + status_algorithm + ;; + *) + echo "Usage: $0 {start|stop|restart|status}" + exit 1 + ;; +esac + +exit $? \ No newline at end of file