From 57cc6c2d8fe4147a9cd81601b4deb9f0c6a9a6a4 Mon Sep 17 00:00:00 2001 From: tinkle-community Date: Thu, 30 Oct 2025 18:20:25 +0800 Subject: [PATCH] DevOps: Add PM2 deployment scripts Add complete PM2 deployment solution: - pm2.config.js: Dynamic path configuration - pm2.sh: One-click management script - PM2_DEPLOYMENT.md: Deployment guide Co-Authored-By: tinkle-community --- PM2_DEPLOYMENT.md | 300 ++++++++++++++++++++++++++++++++++++++++++++++ pm2.config.js | 41 +++++++ pm2.sh | 258 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 599 insertions(+) create mode 100644 PM2_DEPLOYMENT.md create mode 100644 pm2.config.js create mode 100755 pm2.sh diff --git a/PM2_DEPLOYMENT.md b/PM2_DEPLOYMENT.md new file mode 100644 index 00000000..79af7e21 --- /dev/null +++ b/PM2_DEPLOYMENT.md @@ -0,0 +1,300 @@ +# NoFX Trading Bot - PM2 部署指南 + +使用 PM2 进行本地开发和生产部署的完整指南。 + +## 🚀 快速开始 + +### 1. 安装 PM2 + +```bash +npm install -g pm2 +``` + +### 2. 一键启动 + +```bash +./pm2.sh start +``` + +就这么简单!前后端将自动启动。 + +--- + +## 📋 所有命令 + +### 服务管理 + +```bash +# 启动服务 +./pm2.sh start + +# 停止服务 +./pm2.sh stop + +# 重启服务 +./pm2.sh restart + +# 查看状态 +./pm2.sh status + +# 删除服务 +./pm2.sh delete +``` + +### 日志查看 + +```bash +# 查看所有日志(实时) +./pm2.sh logs + +# 只看后端日志 +./pm2.sh logs backend + +# 只看前端日志 +./pm2.sh logs frontend +``` + +### 构建与编译 + +```bash +# 编译后端 +./pm2.sh build + +# 重新编译后端并重启 +./pm2.sh rebuild +``` + +### 监控 + +```bash +# 打开 PM2 监控面板(实时CPU/内存) +./pm2.sh monitor +``` + +--- + +## 📊 访问地址 + +启动成功后: + +- **前端 Web 界面**: http://localhost:3000 +- **后端 API**: http://localhost:8080 +- **健康检查**: http://localhost:8080/health + +--- + +## 🔧 配置文件 + +### pm2.config.js + +PM2 配置文件,定义了前后端的启动参数: + +```javascript +const path = require('path'); + +module.exports = { + apps: [ + { + name: 'nofx-backend', + script: './nofx', // Go 二进制文件 + cwd: __dirname, // 动态获取当前目录 + autorestart: true, + max_memory_restart: '500M' + }, + { + name: 'nofx-frontend', + script: 'npm', + args: 'run dev', // Vite 开发服务器 + cwd: path.join(__dirname, 'web'), // 动态拼接路径 + autorestart: true, + max_memory_restart: '300M' + } + ] +}; +``` + +**修改配置后需要重启:** +```bash +./pm2.sh restart +``` + +--- + +## 📝 日志文件位置 + +- **后端日志**: `./logs/backend-error.log` 和 `./logs/backend-out.log` +- **前端日志**: `./web/logs/frontend-error.log` 和 `./web/logs/frontend-out.log` + +--- + +## 🔄 开机自启动 + +设置 PM2 开机自启动: + +```bash +# 1. 启动服务 +./pm2.sh start + +# 2. 保存当前进程列表 +pm2 save + +# 3. 生成启动脚本 +pm2 startup + +# 4. 按照提示执行命令(需要 sudo) +``` + +**取消开机自启动:** +```bash +pm2 unstartup +``` + +--- + +## 🛠️ 常见操作 + +### 修改代码后重启 + +**后端修改:** +```bash +./pm2.sh rebuild # 自动编译并重启 +``` + +**前端修改:** +```bash +./pm2.sh restart # Vite 会自动热重载,无需重启 +``` + +### 查看实时资源占用 + +```bash +./pm2.sh monitor +``` + +### 查看详细信息 + +```bash +pm2 info nofx-backend # 后端详情 +pm2 info nofx-frontend # 前端详情 +``` + +### 清空日志 + +```bash +pm2 flush +``` + +--- + +## 🐛 故障排查 + +### 服务启动失败 + +```bash +# 1. 查看详细错误 +./pm2.sh logs + +# 2. 检查端口占用 +lsof -i :8080 # 后端端口 +lsof -i :3000 # 前端端口 + +# 3. 手动编译测试 +go build -o nofx +./nofx +``` + +### 后端无法启动 + +```bash +# 检查 config.json 是否存在 +ls -l config.json + +# 检查权限 +chmod +x nofx + +# 手动运行看报错 +./nofx +``` + +### 前端无法访问 + +```bash +# 检查 node_modules +cd web && npm install + +# 手动启动测试 +npm run dev +``` + +--- + +## 🎯 生产环境建议 + +### 1. 使用生产模式 + +修改 `pm2.config.js`: + +```javascript +{ + name: 'nofx-frontend', + script: 'npm', + args: 'run preview', // 改为 preview(需先 npm run build) + env: { + NODE_ENV: 'production' + } +} +``` + +### 2. 增加实例数(负载均衡) + +```javascript +{ + name: 'nofx-backend', + script: './nofx', + instances: 2, // 启动 2 个实例 + exec_mode: 'cluster' +} +``` + +### 3. 自动重启策略 + +```javascript +{ + autorestart: true, + max_restarts: 10, + min_uptime: '10s', + max_memory_restart: '500M' +} +``` + +--- + +## 📦 与 Docker 部署的对比 + +| 特性 | PM2 部署 | Docker 部署 | +|------|---------|------------| +| 启动速度 | ⚡ 快 | 🐌 较慢 | +| 资源占用 | 💚 低 | 🟡 中等 | +| 隔离性 | 🟡 中等 | 💚 高 | +| 适用场景 | 开发/单机 | 生产/集群 | +| 配置复杂度 | 💚 简单 | 🟡 中等 | + +**建议:** +- **开发环境**: 使用 `./pm2.sh` +- **生产环境**: 使用 `./start.sh` (Docker) + +--- + +## 🆘 获取帮助 + +```bash +./pm2.sh help +``` + +或查看 PM2 官方文档:https://pm2.keymetrics.io/ + +--- + +## 📄 License + +MIT diff --git a/pm2.config.js b/pm2.config.js new file mode 100644 index 00000000..2f166388 --- /dev/null +++ b/pm2.config.js @@ -0,0 +1,41 @@ +const path = require('path'); + +module.exports = { + apps: [ + { + name: 'nofx-backend', + script: './nofx', + cwd: __dirname, // 使用当前目录(配置文件所在目录) + interpreter: 'none', // 不使用解释器,直接执行二进制文件 + instances: 1, + autorestart: true, + watch: false, + max_memory_restart: '500M', + env: { + NODE_ENV: 'production' + }, + error_file: './logs/backend-error.log', + out_file: './logs/backend-out.log', + log_date_format: 'YYYY-MM-DD HH:mm:ss Z', + merge_logs: true + }, + { + name: 'nofx-frontend', + script: 'npm', + args: 'run dev', + cwd: path.join(__dirname, 'web'), // 动态拼接 web 目录 + instances: 1, + autorestart: true, + watch: false, + max_memory_restart: '300M', + env: { + NODE_ENV: 'development', + PORT: 3000 + }, + error_file: './logs/frontend-error.log', + out_file: './logs/frontend-out.log', + log_date_format: 'YYYY-MM-DD HH:mm:ss Z', + merge_logs: true + } + ] +}; diff --git a/pm2.sh b/pm2.sh new file mode 100755 index 00000000..b55c8412 --- /dev/null +++ b/pm2.sh @@ -0,0 +1,258 @@ +#!/bin/bash + +# NoFX Trading Bot - PM2 管理脚本 +# 用法: ./pm2.sh [start|stop|restart|status|logs|build] + +set -e + +# 自动获取脚本所在目录(支持符号链接) +PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +cd "$PROJECT_ROOT" + +# 颜色输出 +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +PURPLE='\033[0;35m' +CYAN='\033[0;36m' +NC='\033[0m' # No Color + +# 函数:打印带颜色的消息 +print_info() { + echo -e "${BLUE}ℹ️ $1${NC}" +} + +print_success() { + echo -e "${GREEN}✅ $1${NC}" +} + +print_warning() { + echo -e "${YELLOW}⚠️ $1${NC}" +} + +print_error() { + echo -e "${RED}❌ $1${NC}" +} + +print_header() { + echo -e "${PURPLE}═══════════════════════════════════════${NC}" + echo -e "${PURPLE} 🤖 NoFX Trading Bot - PM2 Manager${NC}" + echo -e "${PURPLE}═══════════════════════════════════════${NC}" + echo "" +} + +# 函数:检查 PM2 是否安装 +check_pm2() { + if ! command -v pm2 &> /dev/null; then + print_error "PM2 未安装,请先安装: npm install -g pm2" + exit 1 + fi +} + +# 函数:确保日志目录存在 +ensure_log_dirs() { + mkdir -p "$PROJECT_ROOT/logs" + mkdir -p "$PROJECT_ROOT/web/logs" + print_info "日志目录已创建" +} + +# 函数:编译后端 +build_backend() { + print_info "正在编译后端..." + go build -o nofx + if [ $? -eq 0 ]; then + print_success "后端编译完成" + else + print_error "后端编译失败" + exit 1 + fi +} + +# 函数:构建前端(生产环境) +build_frontend() { + print_info "正在构建前端..." + cd web + npm run build + if [ $? -eq 0 ]; then + print_success "前端构建完成" + cd .. + else + print_error "前端构建失败" + exit 1 + fi +} + +# 函数:启动服务 +start_services() { + print_header + ensure_log_dirs + + # 检查后端二进制文件是否存在 + if [ ! -f "./nofx" ]; then + print_warning "后端二进制文件不存在,开始编译..." + build_backend + fi + + print_info "正在启动服务..." + pm2 start pm2.config.js + + sleep 2 + pm2 status + + echo "" + print_success "服务启动完成!" + echo "" + echo -e "${CYAN}📊 访问地址:${NC}" + echo -e " ${GREEN}前端:${NC} http://localhost:3000" + echo -e " ${GREEN}后端 API:${NC} http://localhost:8080" + echo "" + echo -e "${CYAN}📝 查看日志:${NC}" + echo -e " ${GREEN}实时日志:${NC} ./pm2.sh logs" + echo -e " ${GREEN}后端日志:${NC} ./pm2.sh logs backend" + echo -e " ${GREEN}前端日志:${NC} ./pm2.sh logs frontend" + echo "" +} + +# 函数:停止服务 +stop_services() { + print_header + print_info "正在停止服务..." + pm2 stop pm2.config.js + print_success "服务已停止" +} + +# 函数:重启服务 +restart_services() { + print_header + print_info "正在重启服务..." + pm2 restart pm2.config.js + sleep 2 + pm2 status + print_success "服务已重启" +} + +# 函数:删除服务 +delete_services() { + print_header + print_warning "正在删除 PM2 服务..." + pm2 delete pm2.config.js || true + print_success "PM2 服务已删除" +} + +# 函数:查看状态 +show_status() { + print_header + pm2 status + echo "" + print_info "详细信息:" + pm2 info nofx-backend + echo "" + pm2 info nofx-frontend +} + +# 函数:查看日志 +show_logs() { + if [ -z "$2" ]; then + # 显示所有日志 + pm2 logs + elif [ "$2" = "backend" ]; then + pm2 logs nofx-backend + elif [ "$2" = "frontend" ]; then + pm2 logs nofx-frontend + else + print_error "未知的日志类型: $2" + print_info "用法: ./pm2.sh logs [backend|frontend]" + exit 1 + fi +} + +# 函数:监控 +show_monitor() { + print_header + print_info "启动 PM2 监控面板..." + pm2 monit +} + +# 函数:重新编译并重启 +rebuild_and_restart() { + print_header + print_info "正在重新编译后端..." + build_backend + + print_info "正在重启后端服务..." + pm2 restart nofx-backend + + sleep 2 + pm2 status + print_success "后端已重新编译并重启" +} + +# 函数:显示帮助 +show_help() { + print_header + echo -e "${CYAN}使用方法:${NC}" + echo " ./pm2.sh [command]" + echo "" + echo -e "${CYAN}可用命令:${NC}" + echo -e " ${GREEN}start${NC} - 启动前后端服务" + echo -e " ${GREEN}stop${NC} - 停止所有服务" + echo -e " ${GREEN}restart${NC} - 重启所有服务" + echo -e " ${GREEN}status${NC} - 查看服务状态" + echo -e " ${GREEN}logs${NC} - 查看所有日志 (Ctrl+C 退出)" + echo -e " ${GREEN}logs backend${NC} - 查看后端日志" + echo -e " ${GREEN}logs frontend${NC} - 查看前端日志" + echo -e " ${GREEN}monitor${NC} - 打开 PM2 监控面板" + echo -e " ${GREEN}build${NC} - 编译后端" + echo -e " ${GREEN}rebuild${NC} - 重新编译后端并重启" + echo -e " ${GREEN}delete${NC} - 删除 PM2 服务" + echo -e " ${GREEN}help${NC} - 显示此帮助信息" + echo "" + echo -e "${CYAN}示例:${NC}" + echo " ./pm2.sh start # 启动服务" + echo " ./pm2.sh logs backend # 查看后端日志" + echo " ./pm2.sh rebuild # 重新编译后端并重启" + echo "" +} + +# 主逻辑 +check_pm2 + +case "${1:-help}" in + start) + start_services + ;; + stop) + stop_services + ;; + restart) + restart_services + ;; + status) + show_status + ;; + logs) + show_logs "$@" + ;; + monitor|mon) + show_monitor + ;; + build) + build_backend + ;; + rebuild) + rebuild_and_restart + ;; + delete|remove) + delete_services + ;; + help|--help|-h) + show_help + ;; + *) + print_error "未知命令: $1" + echo "" + show_help + exit 1 + ;; +esac