diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..f1f0b03 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,13 @@ +# 强制 Shell 脚本使用 LF,避免 Linux 上 $'\r': command not found +*.sh text eol=lf +deploy.sh text eol=lf + +# 其他应在 Linux 服务器运行的文本文件 +*.py text eol=lf +*.js text eol=lf +*.md text eol=lf +*.txt text eol=lf +*.yml text eol=lf +*.yaml text eol=lf +.gitignore text eol=lf +.gitattributes text eol=lf diff --git a/DEPLOY.md b/DEPLOY.md index b9b5abe..a5c3589 100644 --- a/DEPLOY.md +++ b/DEPLOY.md @@ -1,605 +1,607 @@ -# Trading Studio 部署指南 (DEPLOY.md) - -本文档面向 **Ubuntu 物理服务器**(搭载 RTX 3060 Ti,已锁定 120W 功耗墙)的完整环境配置与 PM2 常驻部署流程。适用于首次安装或迁移重装场景。 - -**标准安装路径:** `/opt/Trading_Studio`(root 用户) -**Git 仓库:** https://git.bz121.com/dekun/Trading_Studio.git - ---- - -## 目录 - -0. [**一键部署(推荐)**](#0-一键部署推荐) -1. [硬件与系统前提](#1-硬件与系统前提) -2. [3060 Ti 120W 功耗墙配置](#2-3060-ti-120w-功耗墙配置) -3. [NVIDIA 驱动与 CUDA](#3-nvidia-驱动与-cuda) -4. [Python 虚拟环境](#4-python-虚拟环境) -5. [PyTorch CUDA 12.1 安装](#5-pytorch-cuda-121-安装) -6. [项目依赖安装](#6-项目依赖安装) -7. [远程 Ollama 节点配置](#7-远程-ollama-节点配置) -8. [首次运行与验证](#8-首次运行与验证) -9. [PM2 进程守护](#9-pm2-进程守护) -10. [迁移与故障排查](#10-迁移与故障排查) - ---- - -## 0. 一键部署(推荐) - -项目内置 `deploy.sh`,以 **root** 用户将 Trading Studio 部署到 `/opt/Trading_Studio`,并自动完成依赖安装、虚拟环境、PyTorch CUDA、PM2 常驻与开机自启。 - -### 0.1 前提条件 - -在运行脚本前,请确保服务器已满足: - -| 项目 | 说明 | -|------|------| -| 系统 | Ubuntu 22.04 / 24.04 LTS | -| 用户 | **root**(`sudo -i` 切换) | -| GPU 驱动 | `nvidia-smi` 可正常输出 | -| 网络 | 可访问 `git.bz121.com` 拉取代码 | -| Ollama | 局域网 `192.168.8.64:11434` 可达(润色功能) | - -> **Git 认证:** 若 `git clone` 需要登录,请先在 root 下配置 HTTPS 凭据或 SSH 密钥,再执行部署脚本。 - -### 0.2 首次一键部署 - -```bash -# 切换 root -sudo -i - -# 方式 A:从 Git 克隆后执行(推荐) -git clone https://git.bz121.com/dekun/Trading_Studio.git /opt/Trading_Studio -cd /opt/Trading_Studio -chmod +x deploy.sh -bash deploy.sh - -# 方式 B:若已有本地代码目录,直接在该目录执行 -cd /opt/Trading_Studio -chmod +x deploy.sh -bash deploy.sh -``` - -脚本自动执行以下步骤: - -1. 安装系统依赖(python3、ffmpeg、libsndfile 等) -2. 安装 Node.js 20 + PM2 -3. 克隆/更新代码到 `/opt/Trading_Studio` -4. 创建 `venv/` 并安装 PyTorch cu121 + requirements.txt -5. 创建 `logs/`、`uploads/`、`outputs/` 目录 -6. 设置 GPU 120W 功耗墙(若 nvidia-smi 可用) -7. 放行防火墙端口 5683(若 ufw 已启用) -8. `pm2 start ecosystem.config.js` 并配置开机自启 - -部署成功后访问: - -``` -http://<服务器局域网IP>:5683 -``` - -### 0.3 脚本命令速查 - -```bash -cd /opt/Trading_Studio - -bash deploy.sh # 首次完整部署 + PM2 启动 -bash deploy.sh update # git pull + 更新依赖 + PM2 重启 -bash deploy.sh restart # 仅重启 PM2 -bash deploy.sh stop # 停止 PM2 -bash deploy.sh status # 查看 PM2 / GPU / 端口状态 -bash deploy.sh logs # 查看 PM2 最近 80 行日志 -bash deploy.sh help # 显示帮助 -``` - -### 0.4 日常更新流程 - -代码推送到 Git 后,在服务器上执行: - -```bash -sudo -i -cd /opt/Trading_Studio -bash deploy.sh update -``` - -### 0.5 PM2 运维(root 环境) - -```bash -pm2 status # 进程状态 -pm2 logs trading_studio # 实时日志 -pm2 restart trading_studio # 手动重启 -pm2 monit # 资源监控 - -# 应用日志 -tail -f /opt/Trading_Studio/trading_studio.log -tail -f /opt/Trading_Studio/logs/pm2-out.log -``` - -### 0.6 目录布局(/opt 标准路径) - -``` -/opt/Trading_Studio/ -├── deploy.sh # 一键部署脚本 -├── app.py # Gradio 主入口 -├── venv/ # Python 虚拟环境 -├── logs/ # PM2 日志 -├── uploads/ # 上传临时文件 -├── outputs/ # 合成 wav 输出 -├── speaker_emb.pt # 音色文件(Web UI 生成,需手动备份) -└── trading_studio.log # 应用日志 -``` - ---- - -## 1. 硬件与系统前提 - -| 项目 | 要求 | -|------|------| -| GPU | NVIDIA RTX 3060 Ti 8GB | -| 功耗墙 | 120W(推荐锁定,见下文) | -| 系统 | Ubuntu 22.04 / 24.04 LTS | -| 内存 | ≥ 16GB | -| 磁盘 | ≥ 30GB 可用(含模型缓存) | -| 网络 | 局域网可访问 `192.168.8.64:11434` | - -```bash -# 基础工具 -sudo apt update && sudo apt upgrade -y -sudo apt install -y git curl wget build-essential \ - python3 python3-venv python3-dev \ - ffmpeg libsndfile1 portaudio19-dev -``` - -> 若 `python3-venv` 包名报错,使用 `python3-venv`。 - ---- - -## 2. 3060 Ti 120W 功耗墙配置 - -锁定 GPU 功耗有助于稳定 7×24 运行、降低散热压力,避免 Whisper + ChatTTS 并发时触发功耗波动。 - -### 2.1 安装 nvidia-smi 功耗管理工具 - -驱动安装后自带 `nvidia-smi`。确认 GPU 可见: - -```bash -nvidia-smi -``` - -### 2.2 临时设置 120W 功耗上限 - -```bash -# 查看支持的功耗范围 -nvidia-smi -q -d POWER | grep -A3 "Power Limit" - -# 设置最大功耗为 120W(需 root) -sudo nvidia-smi -pl 120 -``` - -### 2.3 开机持久化(推荐) - -创建 systemd 服务,每次启动自动应用: - -```bash -sudo tee /etc/systemd/system/nvidia-powerlimit.service << 'EOF' -[Unit] -Description=Set NVIDIA GPU Power Limit to 120W -After=multi-user.target - -[Service] -Type=oneshot -ExecStart=/usr/bin/nvidia-smi -pl 120 -RemainAfterExit=yes - -[Install] -WantedBy=multi-user.target -EOF - -sudo systemctl daemon-reload -sudo systemctl enable nvidia-powerlimit.service -sudo systemctl start nvidia-powerlimit.service - -# 验证 -nvidia-smi --query-gpu=power.limit --format=csv -``` - ---- - -## 3. NVIDIA 驱动与 CUDA - -### 3.1 安装驱动(推荐 535+ 或 550+) - -```bash -# Ubuntu 自动安装推荐驱动 -sudo ubuntu-drivers devices -sudo ubuntu-drivers autoinstall -# 或指定版本: sudo apt install nvidia-driver-550 - -sudo reboot -``` - -重启后验证: - -```bash -nvidia-smi -nvcc --version # 若未安装 nvcc 不影响 PyTorch,可选 -``` - -### 3.2 cuDNN(Faster-Whisper / PyTorch 需要) - -PyTorch cu121 wheel 通常自带运行时库。若 Whisper 报 cuDNN 错误: - -```bash -# 参考 NVIDIA 官方文档安装 cuDNN for CUDA 12.x -# https://developer.nvidia.com/cudnn -``` - ---- - -## 4. Python 虚拟环境 - -```bash -# 克隆项目 -cd /opt -git clone https://git.bz121.com/dekun/Trading_Studio.git -cd Trading_Studio - -# 创建虚拟环境(必须使用 venv,与 PM2 interpreter 路径一致) -python3 -m venv venv - -# 激活 -source venv/bin/activate - -# 升级 pip -pip install --upgrade pip setuptools wheel -``` - -**重要:** PM2 配置中 `interpreter` 指向 `./venv/bin/python`,请确保在项目根目录创建 `venv/`。 - ---- - -## 5. PyTorch CUDA 12.1 安装 - -**必须先于其他 GPU 依赖安装**,避免 pip 拉取 CPU 版 torch。 - -```bash -source venv/bin/activate - -pip install torch torchvision torchaudio \ - --index-url https://download.pytorch.org/whl/cu121 -``` - -验证 CUDA 可用: - -```bash -python -c " -import torch -print('PyTorch:', torch.__version__) -print('CUDA available:', torch.cuda.is_available()) -print('GPU:', torch.cuda.get_device_name(0) if torch.cuda.is_available() else 'N/A') -" -``` - -期望输出类似: - -``` -PyTorch: 2.x.x+cu121 -CUDA available: True -GPU: NVIDIA GeForce RTX 3060 Ti -``` - ---- - -## 6. 项目依赖安装 - -```bash -source venv/bin/activate -cd /opt/Trading_Studio - -# 安装其余依赖 -pip install -r requirements.txt -``` - -### 6.1 Faster-Whisper - -随 `requirements.txt` 安装。首次运行会自动下载 `small` 模型(约 500MB)至 HuggingFace 缓存。 - -### 6.2 ChatTTS - -从 GitHub 源码安装(已在 requirements.txt 中指定): - -```bash -pip install ChatTTS @ git+https://github.com/2noise/ChatTTS.git -``` - -首次 `save_fixed_speaker` 或 `generate_voice` 时会下载模型权重(数 GB),请确保网络畅通或提前配置 HuggingFace 镜像: - -```bash -export HF_ENDPOINT=https://hf-mirror.com # 可选,国内加速 -``` - -### 6.3 Gradio - -```bash -pip install gradio>=4.44.0 -``` - ---- - -## 7. 远程 Ollama 节点配置 - -Trading Studio 的 LLM 润色模块连接局域网 Ollama,**不在本机运行大模型**。 - -| 配置项 | 值 | -|--------|-----| -| 地址 | `http://192.168.8.64:11434` | -| API | `POST /api/chat` | -| 模型 | `huihui_ai/gemma-4-abliterated:e4b` | -| 流式 | `stream: false` | - -### 7.1 在 Ollama 节点(192.168.8.64)上 - -```bash -# 安装 Ollama(若未安装) -curl -fsSL https://ollama.com/install.sh | sh - -# 拉取模型 -ollama pull huihui_ai/gemma-4-abliterated:e4b - -# 允许局域网访问(编辑 systemd 或环境变量) -sudo systemctl edit ollama -``` - -添加: - -```ini -[Service] -Environment="OLLAMA_HOST=0.0.0.0:11434" -``` - -```bash -sudo systemctl daemon-reload -sudo systemctl restart ollama -``` - -### 7.2 在本机(Trading Studio 服务器)验证 - -```bash -curl http://192.168.8.64:11434/api/tags - -curl http://192.168.8.64:11434/api/chat -d '{ - "model": "huihui_ai/gemma-4-abliterated:e4b", - "messages": [{"role": "user", "content": "ping"}], - "stream": false -}' -``` - ---- - -## 8. 首次运行与验证 - -```bash -source venv/bin/activate -cd /opt/Trading_Studio - -# 前台启动(调试) -python app.py -``` - -浏览器访问: - -``` -http://<本机局域网IP>:5683 -``` - -### 8.1 验证清单 - -- [ ] 页面加载,Ollama 状态显示在线 -- [ ] 上传 10-30s 参考人声 → 音色锁定成功,生成 `speaker_emb.pt` -- [ ] 上传复盘录音 → Whisper 识别出中文文本 -- [ ] 点击润色 → 返回 Gemma4 处理后的文稿 -- [ ] 点击合成 → `outputs/` 下生成 24kHz wav - -### 8.2 日志位置 - -- 应用日志:`trading_studio.log`(项目根目录) -- PM2 日志:`logs/pm2-out.log`、`logs/pm2-error.log` - -```bash -mkdir -p logs -``` - ---- - -## 9. PM2 进程守护 - -Trading Studio 原生支持 PM2 常驻管理,确保 Gradio 服务崩溃后自动重启、开机自启。 - -### 9.1 安装 Node.js 与 PM2 - -```bash -# 安装 Node.js 20 LTS -curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - -sudo apt install -y nodejs - -# 全局安装 PM2 -sudo npm install -g pm2 -``` - -### 9.2 方式 A:使用 ecosystem.config.js(推荐) - -项目已内置 `ecosystem.config.js`: - -```javascript -module.exports = { - apps: [{ - name: "trading_studio", - script: "app.py", - interpreter: "./venv/bin/python", - cwd: __dirname, - instances: 1, - autorestart: true, - max_memory_restart: "6G", - env: { - PYTHONUNBUFFERED: "1", - CUDA_VISIBLE_DEVICES: "0", - }, - }], -}; -``` - -启动: - -```bash -cd /opt/Trading_Studio -mkdir -p logs - -pm2 start ecosystem.config.js -pm2 status -pm2 logs trading_studio --lines 50 -``` - -> **推荐:** 直接使用 `bash deploy.sh` 一键完成上述步骤,见 [第 0 节](#0-一键部署推荐)。 - -### 9.3 方式 B:直接命令行 - -```bash -cd /opt/Trading_Studio - -pm2 start app.py \ - --name "trading_studio" \ - --interpreter ./venv/bin/python - -pm2 save -``` - -### 9.4 开机自启 - -```bash -pm2 startup -# 按提示执行输出的 sudo 命令 - -pm2 save -``` - -### 9.5 常用运维命令 - -```bash -pm2 restart trading_studio # 重启(改代码后) -pm2 stop trading_studio # 停止 -pm2 delete trading_studio # 移除 -pm2 monit # 实时监控 CPU/内存 -``` - -### 9.6 更新代码后重新部署 - -```bash -cd /opt/Trading_Studio -bash deploy.sh update -``` - -或手动: - -```bash -cd /opt/Trading_Studio -git pull -source venv/bin/activate -pip install -r requirements.txt # 若有新依赖 -pm2 restart trading_studio -``` - ---- - -## 10. 迁移与故障排查 - -### 10.1 迁移到新机器 - -1. 备份 `/opt/Trading_Studio/speaker_emb.pt`(音色文件,不入 Git) -2. 新机器执行 `bash deploy.sh` 一键部署 -3. 将 `speaker_emb.pt` 复制回 `/opt/Trading_Studio/` -4. `bash deploy.sh restart` - -### 10.2 CUDA / 显存问题 - -```bash -# 查看显存占用 -nvidia-smi - -# 若 OOM,确保无其他 GPU 进程 -fuser -v /dev/nvidia* -``` - -Whisper 与 ChatTTS 不会同时常驻最大显存,但首次加载模型时峰值较高。建议: - -- 锁定 120W 功耗墙 -- `max_memory_restart: "6G"` 已在 PM2 配置中设置 - -### 10.3 Whisper CUDA 报错 - -``` -错误: CUDA initialization failed / out of memory -``` - -处理: - -1. 重启 PM2 进程释放显存 -2. 确认 `compute_type="float16"`(已在 config.py 配置) -3. 降级模型为 `base`(修改 `config.py` 中 `WHISPER_MODEL_SIZE`) - -### 10.4 Ollama 超时 - -``` -连接 Ollama 超时(>60s) -``` - -处理: - -1. 确认 Ollama 节点模型已预加载:`ollama run huihui_ai/gemma-4-abliterated:e4b` -2. 增大 `config.py` 中 `OLLAMA_TIMEOUT` -3. 检查防火墙:`sudo ufw allow from 192.168.8.0/24 to any port 11434`(在 Ollama 节点) - -### 10.5 ChatTTS 音色文件损坏 - -```bash -rm speaker_emb.pt -# 重新在 Web UI「音色锁定」上传参考人声 -``` - -### 10.6 端口 5683 被占用 - -```bash -sudo lsof -i :5683 -# 或 -ss -tlnp | grep 5683 -``` - ---- - -## 附录:防火墙(本机 Gradio) - -若需局域网其他设备访问 Web UI: - -```bash -sudo ufw allow 5683/tcp -sudo ufw reload -``` - -访问地址:`http://<服务器局域网IP>:5683` - ---- - -## 附录:config.py 关键常量速查 - -```python -HOST = "0.0.0.0" -PORT = 5683 -OLLAMA_URL = "http://192.168.8.64:11434/api/chat" -MODEL_NAME = "huihui_ai/gemma-4-abliterated:e4b" -WHISPER_MODEL_SIZE = "small" -WHISPER_DEVICE = "cuda" -WHISPER_COMPUTE_TYPE = "float16" -SPEAKER_EMB_PATH = "speaker_emb.pt" -TTS_SAMPLE_RATE = 24000 -``` - ---- - -**部署完成后,请先在「音色锁定」模块完成首次音色提取,再进行日常复盘配音生产。** +# Trading Studio 部署指南 (DEPLOY.md) + +本文档面向 **Ubuntu 物理服务器**(搭载 RTX 3060 Ti,已锁定 120W 功耗墙)的完整环境配置与 PM2 常驻部署流程。适用于首次安装或迁移重装场景。 + +**标准安装路径:** `/opt/Trading_Studio`(root 用户) +**Git 仓库:** https://git.bz121.com/dekun/Trading_Studio.git + +--- + +## 目录 + +0. [**一键部署(推荐)**](#0-一键部署推荐) +1. [硬件与系统前提](#1-硬件与系统前提) +2. [3060 Ti 120W 功耗墙配置](#2-3060-ti-120w-功耗墙配置) +3. [NVIDIA 驱动与 CUDA](#3-nvidia-驱动与-cuda) +4. [Python 虚拟环境](#4-python-虚拟环境) +5. [PyTorch CUDA 12.1 安装](#5-pytorch-cuda-121-安装) +6. [项目依赖安装](#6-项目依赖安装) +7. [远程 Ollama 节点配置](#7-远程-ollama-节点配置) +8. [首次运行与验证](#8-首次运行与验证) +9. [PM2 进程守护](#9-pm2-进程守护) +10. [迁移与故障排查](#10-迁移与故障排查) + +--- + +## 0. 一键部署(推荐) + +项目内置 `deploy.sh`,以 **root** 用户将 Trading Studio 部署到 `/opt/Trading_Studio`,并自动完成依赖安装、虚拟环境、PyTorch CUDA、PM2 常驻与开机自启。 + +### 0.1 前提条件 + +在运行脚本前,请确保服务器已满足: + +| 项目 | 说明 | +|------|------| +| 系统 | Ubuntu 22.04 / 24.04 LTS | +| 用户 | **root**(`sudo -i` 切换) | +| GPU 驱动 | `nvidia-smi` 可正常输出 | +| 网络 | 可访问 `git.bz121.com` 拉取代码 | +| Ollama | 局域网 `192.168.8.64:11434` 可达(润色功能) | + +> **Git 认证:** 若 `git clone` 需要登录,请先在 root 下配置 HTTPS 凭据或 SSH 密钥,再执行部署脚本。 + +### 0.2 首次一键部署 + +```bash +# 切换 root +sudo -i + +# 方式 A:从 Git 克隆后执行(推荐) +git clone https://git.bz121.com/dekun/Trading_Studio.git /opt/Trading_Studio +cd /opt/Trading_Studio +chmod +x deploy.sh +bash deploy.sh + +# 方式 B:若已有本地代码目录,直接在该目录执行 +cd /opt/Trading_Studio +chmod +x deploy.sh +bash deploy.sh +``` + +> **若报错 `$'\r': command not found`:** 说明脚本含 Windows 换行符,先执行 `sed -i 's/\r$//' deploy.sh` 再重试,或 `git pull` 拉取已修复版本。 + +脚本自动执行以下步骤: + +1. 安装系统依赖(python3、ffmpeg、libsndfile 等) +2. 安装 Node.js 20 + PM2 +3. 克隆/更新代码到 `/opt/Trading_Studio` +4. 创建 `venv/` 并安装 PyTorch cu121 + requirements.txt +5. 创建 `logs/`、`uploads/`、`outputs/` 目录 +6. 设置 GPU 120W 功耗墙(若 nvidia-smi 可用) +7. 放行防火墙端口 5683(若 ufw 已启用) +8. `pm2 start ecosystem.config.js` 并配置开机自启 + +部署成功后访问: + +``` +http://<服务器局域网IP>:5683 +``` + +### 0.3 脚本命令速查 + +```bash +cd /opt/Trading_Studio + +bash deploy.sh # 首次完整部署 + PM2 启动 +bash deploy.sh update # git pull + 更新依赖 + PM2 重启 +bash deploy.sh restart # 仅重启 PM2 +bash deploy.sh stop # 停止 PM2 +bash deploy.sh status # 查看 PM2 / GPU / 端口状态 +bash deploy.sh logs # 查看 PM2 最近 80 行日志 +bash deploy.sh help # 显示帮助 +``` + +### 0.4 日常更新流程 + +代码推送到 Git 后,在服务器上执行: + +```bash +sudo -i +cd /opt/Trading_Studio +bash deploy.sh update +``` + +### 0.5 PM2 运维(root 环境) + +```bash +pm2 status # 进程状态 +pm2 logs trading_studio # 实时日志 +pm2 restart trading_studio # 手动重启 +pm2 monit # 资源监控 + +# 应用日志 +tail -f /opt/Trading_Studio/trading_studio.log +tail -f /opt/Trading_Studio/logs/pm2-out.log +``` + +### 0.6 目录布局(/opt 标准路径) + +``` +/opt/Trading_Studio/ +├── deploy.sh # 一键部署脚本 +├── app.py # Gradio 主入口 +├── venv/ # Python 虚拟环境 +├── logs/ # PM2 日志 +├── uploads/ # 上传临时文件 +├── outputs/ # 合成 wav 输出 +├── speaker_emb.pt # 音色文件(Web UI 生成,需手动备份) +└── trading_studio.log # 应用日志 +``` + +--- + +## 1. 硬件与系统前提 + +| 项目 | 要求 | +|------|------| +| GPU | NVIDIA RTX 3060 Ti 8GB | +| 功耗墙 | 120W(推荐锁定,见下文) | +| 系统 | Ubuntu 22.04 / 24.04 LTS | +| 内存 | ≥ 16GB | +| 磁盘 | ≥ 30GB 可用(含模型缓存) | +| 网络 | 局域网可访问 `192.168.8.64:11434` | + +```bash +# 基础工具 +sudo apt update && sudo apt upgrade -y +sudo apt install -y git curl wget build-essential \ + python3 python3-venv python3-dev \ + ffmpeg libsndfile1 portaudio19-dev +``` + +> 若 `python3-venv` 包名报错,使用 `python3-venv`。 + +--- + +## 2. 3060 Ti 120W 功耗墙配置 + +锁定 GPU 功耗有助于稳定 7×24 运行、降低散热压力,避免 Whisper + ChatTTS 并发时触发功耗波动。 + +### 2.1 安装 nvidia-smi 功耗管理工具 + +驱动安装后自带 `nvidia-smi`。确认 GPU 可见: + +```bash +nvidia-smi +``` + +### 2.2 临时设置 120W 功耗上限 + +```bash +# 查看支持的功耗范围 +nvidia-smi -q -d POWER | grep -A3 "Power Limit" + +# 设置最大功耗为 120W(需 root) +sudo nvidia-smi -pl 120 +``` + +### 2.3 开机持久化(推荐) + +创建 systemd 服务,每次启动自动应用: + +```bash +sudo tee /etc/systemd/system/nvidia-powerlimit.service << 'EOF' +[Unit] +Description=Set NVIDIA GPU Power Limit to 120W +After=multi-user.target + +[Service] +Type=oneshot +ExecStart=/usr/bin/nvidia-smi -pl 120 +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target +EOF + +sudo systemctl daemon-reload +sudo systemctl enable nvidia-powerlimit.service +sudo systemctl start nvidia-powerlimit.service + +# 验证 +nvidia-smi --query-gpu=power.limit --format=csv +``` + +--- + +## 3. NVIDIA 驱动与 CUDA + +### 3.1 安装驱动(推荐 535+ 或 550+) + +```bash +# Ubuntu 自动安装推荐驱动 +sudo ubuntu-drivers devices +sudo ubuntu-drivers autoinstall +# 或指定版本: sudo apt install nvidia-driver-550 + +sudo reboot +``` + +重启后验证: + +```bash +nvidia-smi +nvcc --version # 若未安装 nvcc 不影响 PyTorch,可选 +``` + +### 3.2 cuDNN(Faster-Whisper / PyTorch 需要) + +PyTorch cu121 wheel 通常自带运行时库。若 Whisper 报 cuDNN 错误: + +```bash +# 参考 NVIDIA 官方文档安装 cuDNN for CUDA 12.x +# https://developer.nvidia.com/cudnn +``` + +--- + +## 4. Python 虚拟环境 + +```bash +# 克隆项目 +cd /opt +git clone https://git.bz121.com/dekun/Trading_Studio.git +cd Trading_Studio + +# 创建虚拟环境(必须使用 venv,与 PM2 interpreter 路径一致) +python3 -m venv venv + +# 激活 +source venv/bin/activate + +# 升级 pip +pip install --upgrade pip setuptools wheel +``` + +**重要:** PM2 配置中 `interpreter` 指向 `./venv/bin/python`,请确保在项目根目录创建 `venv/`。 + +--- + +## 5. PyTorch CUDA 12.1 安装 + +**必须先于其他 GPU 依赖安装**,避免 pip 拉取 CPU 版 torch。 + +```bash +source venv/bin/activate + +pip install torch torchvision torchaudio \ + --index-url https://download.pytorch.org/whl/cu121 +``` + +验证 CUDA 可用: + +```bash +python -c " +import torch +print('PyTorch:', torch.__version__) +print('CUDA available:', torch.cuda.is_available()) +print('GPU:', torch.cuda.get_device_name(0) if torch.cuda.is_available() else 'N/A') +" +``` + +期望输出类似: + +``` +PyTorch: 2.x.x+cu121 +CUDA available: True +GPU: NVIDIA GeForce RTX 3060 Ti +``` + +--- + +## 6. 项目依赖安装 + +```bash +source venv/bin/activate +cd /opt/Trading_Studio + +# 安装其余依赖 +pip install -r requirements.txt +``` + +### 6.1 Faster-Whisper + +随 `requirements.txt` 安装。首次运行会自动下载 `small` 模型(约 500MB)至 HuggingFace 缓存。 + +### 6.2 ChatTTS + +从 GitHub 源码安装(已在 requirements.txt 中指定): + +```bash +pip install ChatTTS @ git+https://github.com/2noise/ChatTTS.git +``` + +首次 `save_fixed_speaker` 或 `generate_voice` 时会下载模型权重(数 GB),请确保网络畅通或提前配置 HuggingFace 镜像: + +```bash +export HF_ENDPOINT=https://hf-mirror.com # 可选,国内加速 +``` + +### 6.3 Gradio + +```bash +pip install gradio>=4.44.0 +``` + +--- + +## 7. 远程 Ollama 节点配置 + +Trading Studio 的 LLM 润色模块连接局域网 Ollama,**不在本机运行大模型**。 + +| 配置项 | 值 | +|--------|-----| +| 地址 | `http://192.168.8.64:11434` | +| API | `POST /api/chat` | +| 模型 | `huihui_ai/gemma-4-abliterated:e4b` | +| 流式 | `stream: false` | + +### 7.1 在 Ollama 节点(192.168.8.64)上 + +```bash +# 安装 Ollama(若未安装) +curl -fsSL https://ollama.com/install.sh | sh + +# 拉取模型 +ollama pull huihui_ai/gemma-4-abliterated:e4b + +# 允许局域网访问(编辑 systemd 或环境变量) +sudo systemctl edit ollama +``` + +添加: + +```ini +[Service] +Environment="OLLAMA_HOST=0.0.0.0:11434" +``` + +```bash +sudo systemctl daemon-reload +sudo systemctl restart ollama +``` + +### 7.2 在本机(Trading Studio 服务器)验证 + +```bash +curl http://192.168.8.64:11434/api/tags + +curl http://192.168.8.64:11434/api/chat -d '{ + "model": "huihui_ai/gemma-4-abliterated:e4b", + "messages": [{"role": "user", "content": "ping"}], + "stream": false +}' +``` + +--- + +## 8. 首次运行与验证 + +```bash +source venv/bin/activate +cd /opt/Trading_Studio + +# 前台启动(调试) +python app.py +``` + +浏览器访问: + +``` +http://<本机局域网IP>:5683 +``` + +### 8.1 验证清单 + +- [ ] 页面加载,Ollama 状态显示在线 +- [ ] 上传 10-30s 参考人声 → 音色锁定成功,生成 `speaker_emb.pt` +- [ ] 上传复盘录音 → Whisper 识别出中文文本 +- [ ] 点击润色 → 返回 Gemma4 处理后的文稿 +- [ ] 点击合成 → `outputs/` 下生成 24kHz wav + +### 8.2 日志位置 + +- 应用日志:`trading_studio.log`(项目根目录) +- PM2 日志:`logs/pm2-out.log`、`logs/pm2-error.log` + +```bash +mkdir -p logs +``` + +--- + +## 9. PM2 进程守护 + +Trading Studio 原生支持 PM2 常驻管理,确保 Gradio 服务崩溃后自动重启、开机自启。 + +### 9.1 安装 Node.js 与 PM2 + +```bash +# 安装 Node.js 20 LTS +curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - +sudo apt install -y nodejs + +# 全局安装 PM2 +sudo npm install -g pm2 +``` + +### 9.2 方式 A:使用 ecosystem.config.js(推荐) + +项目已内置 `ecosystem.config.js`: + +```javascript +module.exports = { + apps: [{ + name: "trading_studio", + script: "app.py", + interpreter: "./venv/bin/python", + cwd: __dirname, + instances: 1, + autorestart: true, + max_memory_restart: "6G", + env: { + PYTHONUNBUFFERED: "1", + CUDA_VISIBLE_DEVICES: "0", + }, + }], +}; +``` + +启动: + +```bash +cd /opt/Trading_Studio +mkdir -p logs + +pm2 start ecosystem.config.js +pm2 status +pm2 logs trading_studio --lines 50 +``` + +> **推荐:** 直接使用 `bash deploy.sh` 一键完成上述步骤,见 [第 0 节](#0-一键部署推荐)。 + +### 9.3 方式 B:直接命令行 + +```bash +cd /opt/Trading_Studio + +pm2 start app.py \ + --name "trading_studio" \ + --interpreter ./venv/bin/python + +pm2 save +``` + +### 9.4 开机自启 + +```bash +pm2 startup +# 按提示执行输出的 sudo 命令 + +pm2 save +``` + +### 9.5 常用运维命令 + +```bash +pm2 restart trading_studio # 重启(改代码后) +pm2 stop trading_studio # 停止 +pm2 delete trading_studio # 移除 +pm2 monit # 实时监控 CPU/内存 +``` + +### 9.6 更新代码后重新部署 + +```bash +cd /opt/Trading_Studio +bash deploy.sh update +``` + +或手动: + +```bash +cd /opt/Trading_Studio +git pull +source venv/bin/activate +pip install -r requirements.txt # 若有新依赖 +pm2 restart trading_studio +``` + +--- + +## 10. 迁移与故障排查 + +### 10.1 迁移到新机器 + +1. 备份 `/opt/Trading_Studio/speaker_emb.pt`(音色文件,不入 Git) +2. 新机器执行 `bash deploy.sh` 一键部署 +3. 将 `speaker_emb.pt` 复制回 `/opt/Trading_Studio/` +4. `bash deploy.sh restart` + +### 10.2 CUDA / 显存问题 + +```bash +# 查看显存占用 +nvidia-smi + +# 若 OOM,确保无其他 GPU 进程 +fuser -v /dev/nvidia* +``` + +Whisper 与 ChatTTS 不会同时常驻最大显存,但首次加载模型时峰值较高。建议: + +- 锁定 120W 功耗墙 +- `max_memory_restart: "6G"` 已在 PM2 配置中设置 + +### 10.3 Whisper CUDA 报错 + +``` +错误: CUDA initialization failed / out of memory +``` + +处理: + +1. 重启 PM2 进程释放显存 +2. 确认 `compute_type="float16"`(已在 config.py 配置) +3. 降级模型为 `base`(修改 `config.py` 中 `WHISPER_MODEL_SIZE`) + +### 10.4 Ollama 超时 + +``` +连接 Ollama 超时(>60s) +``` + +处理: + +1. 确认 Ollama 节点模型已预加载:`ollama run huihui_ai/gemma-4-abliterated:e4b` +2. 增大 `config.py` 中 `OLLAMA_TIMEOUT` +3. 检查防火墙:`sudo ufw allow from 192.168.8.0/24 to any port 11434`(在 Ollama 节点) + +### 10.5 ChatTTS 音色文件损坏 + +```bash +rm speaker_emb.pt +# 重新在 Web UI「音色锁定」上传参考人声 +``` + +### 10.6 端口 5683 被占用 + +```bash +sudo lsof -i :5683 +# 或 +ss -tlnp | grep 5683 +``` + +--- + +## 附录:防火墙(本机 Gradio) + +若需局域网其他设备访问 Web UI: + +```bash +sudo ufw allow 5683/tcp +sudo ufw reload +``` + +访问地址:`http://<服务器局域网IP>:5683` + +--- + +## 附录:config.py 关键常量速查 + +```python +HOST = "0.0.0.0" +PORT = 5683 +OLLAMA_URL = "http://192.168.8.64:11434/api/chat" +MODEL_NAME = "huihui_ai/gemma-4-abliterated:e4b" +WHISPER_MODEL_SIZE = "small" +WHISPER_DEVICE = "cuda" +WHISPER_COMPUTE_TYPE = "float16" +SPEAKER_EMB_PATH = "speaker_emb.pt" +TTS_SAMPLE_RATE = 24000 +``` + +--- + +**部署完成后,请先在「音色锁定」模块完成首次音色提取,再进行日常复盘配音生产。** diff --git a/deploy.sh b/deploy.sh index df175f7..e195128 100644 --- a/deploy.sh +++ b/deploy.sh @@ -1,340 +1,340 @@ -#!/usr/bin/env bash -# ============================================================================= -# Trading Studio 一键部署脚本 -# 安装路径: /opt/Trading_Studio -# 运行用户: root -# 功能: 系统依赖 → 代码拉取 → Python 虚拟环境 → PyTorch CUDA → PM2 常驻 -# -# 用法: -# sudo bash deploy.sh # 首次完整部署并 PM2 启动 -# sudo bash deploy.sh update # 拉取最新代码、更新依赖、重启 PM2 -# sudo bash deploy.sh restart # 仅重启 PM2 进程 -# sudo bash deploy.sh stop # 停止 PM2 进程 -# sudo bash deploy.sh status # 查看 PM2 与 GPU 状态 -# sudo bash deploy.sh logs # 查看 PM2 最近日志 -# ============================================================================= - -set -euo pipefail - -# --------------------------------------------------------------------------- -# 可配置常量 -# --------------------------------------------------------------------------- -INSTALL_DIR="/opt/Trading_Studio" -GIT_REPO="https://git.bz121.com/dekun/Trading_Studio.git" -PM2_APP_NAME="trading_studio" -GRADIO_PORT=5683 -GPU_POWER_LIMIT=120 -PYTORCH_INDEX="https://download.pytorch.org/whl/cu121" - -# --------------------------------------------------------------------------- -# 颜色输出 -# --------------------------------------------------------------------------- -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -CYAN='\033[0;36m' -NC='\033[0m' - -log_info() { echo -e "${CYAN}[INFO]${NC} $*"; } -log_ok() { echo -e "${GREEN}[OK]${NC} $*"; } -log_warn() { echo -e "${YELLOW}[WARN]${NC} $*"; } -log_error() { echo -e "${RED}[ERROR]${NC} $*" >&2; } - -# --------------------------------------------------------------------------- -# 前置检查 -# --------------------------------------------------------------------------- -require_root() { - if [[ "${EUID:-$(id -u)}" -ne 0 ]]; then - log_error "请使用 root 用户运行: sudo bash deploy.sh" - exit 1 - fi -} - -check_gpu() { - if command -v nvidia-smi &>/dev/null; then - log_ok "检测到 NVIDIA GPU:" - nvidia-smi --query-gpu=name,driver_version,memory.total --format=csv,noheader - else - log_warn "未检测到 nvidia-smi,Whisper/ChatTTS CUDA 加速可能不可用。" - fi -} - -set_gpu_power_limit() { - if command -v nvidia-smi &>/dev/null; then - log_info "设置 GPU 功耗上限为 ${GPU_POWER_LIMIT}W ..." - if nvidia-smi -pl "${GPU_POWER_LIMIT}" &>/dev/null; then - log_ok "GPU 功耗墙已设为 ${GPU_POWER_LIMIT}W" - else - log_warn "无法设置功耗墙,请手动执行: nvidia-smi -pl ${GPU_POWER_LIMIT}" - fi - fi -} - -# --------------------------------------------------------------------------- -# 系统依赖 -# --------------------------------------------------------------------------- -install_system_deps() { - log_info "安装系统依赖 ..." - apt-get update -qq - apt-get install -y \ - git curl wget build-essential \ - python3 python3-venv python3-dev python3-pip \ - ffmpeg libsndfile1 portaudio19-dev \ - ca-certificates gnupg - - log_ok "系统依赖安装完成" -} - -install_node_pm2() { - if command -v pm2 &>/dev/null; then - log_ok "PM2 已安装: $(pm2 -v)" - return - fi - - log_info "安装 Node.js 20 LTS 与 PM2 ..." - if ! command -v node &>/dev/null; then - curl -fsSL https://deb.nodesource.com/setup_20.x | bash - - apt-get install -y nodejs - fi - npm install -g pm2 - log_ok "PM2 安装完成: $(pm2 -v)" -} - -# --------------------------------------------------------------------------- -# 代码部署 -# --------------------------------------------------------------------------- -deploy_code() { - if [[ -d "${INSTALL_DIR}/.git" ]]; then - log_info "更新已有代码: ${INSTALL_DIR}" - git -C "${INSTALL_DIR}" pull --ff-only || { - log_warn "git pull 失败,尝试保留本地更改继续部署 ..." - } - elif [[ -d "${INSTALL_DIR}" ]]; then - log_error "${INSTALL_DIR} 已存在但不是 git 仓库,请手动处理后重试。" - exit 1 - else - log_info "克隆仓库到 ${INSTALL_DIR} ..." - git clone "${GIT_REPO}" "${INSTALL_DIR}" - fi - log_ok "代码就绪: ${INSTALL_DIR}" -} - -# --------------------------------------------------------------------------- -# Python 环境 -# ------------------------------------------------------------------- -setup_python_venv() { - local venv_path="${INSTALL_DIR}/venv" - - if [[ ! -d "${venv_path}" ]]; then - log_info "创建 Python 虚拟环境 ..." - python3 -m venv "${venv_path}" - fi - - # shellcheck disable=SC1091 - source "${venv_path}/bin/activate" - - log_info "升级 pip ..." - pip install --upgrade pip setuptools wheel -q - - log_info "安装 PyTorch (CUDA 12.1) ..." - pip install torch torchvision torchaudio --index-url "${PYTORCH_INDEX}" -q - - log_info "安装项目依赖 ..." - pip install -r "${INSTALL_DIR}/requirements.txt" -q - - # 验证 CUDA - if python -c "import torch; assert torch.cuda.is_available()" 2>/dev/null; then - log_ok "PyTorch CUDA 可用: $(python -c 'import torch; print(torch.cuda.get_device_name(0))')" - else - log_warn "PyTorch CUDA 不可用,请检查 NVIDIA 驱动与 CUDA 运行时。" - fi - - deactivate - log_ok "Python 虚拟环境配置完成" -} - -create_runtime_dirs() { - mkdir -p "${INSTALL_DIR}/logs" - mkdir -p "${INSTALL_DIR}/uploads" - mkdir -p "${INSTALL_DIR}/outputs" - log_ok "运行时目录已创建 (logs, uploads, outputs)" -} - -# --------------------------------------------------------------------------- -# 防火墙 -# --------------------------------------------------------------------------- -configure_firewall() { - if command -v ufw &>/dev/null && ufw status | grep -q "Status: active"; then - log_info "放行 Gradio 端口 ${GRADIO_PORT} ..." - ufw allow "${GRADIO_PORT}/tcp" || true - log_ok "防火墙规则已更新" - else - log_info "ufw 未启用,跳过防火墙配置" - fi -} - -# --------------------------------------------------------------------------- -# PM2 管理 -# --------------------------------------------------------------------------- -pm2_start() { - log_info "通过 PM2 启动 Trading Studio ..." - cd "${INSTALL_DIR}" - - # 若已有同名进程则先删除再启动,避免重复 - if pm2 describe "${PM2_APP_NAME}" &>/dev/null; then - pm2 delete "${PM2_APP_NAME}" || true - fi - - pm2 start ecosystem.config.js - pm2 save - - # 配置 root 用户开机自启 - local startup_cmd - startup_cmd=$(pm2 startup systemd -u root --hp /root 2>&1 | grep "sudo env" || true) - if [[ -n "${startup_cmd}" ]]; then - eval "${startup_cmd}" || log_warn "PM2 startup 可能已配置过" - fi - pm2 save - - log_ok "PM2 启动完成" - pm2 status -} - -pm2_restart() { - cd "${INSTALL_DIR}" - if pm2 describe "${PM2_APP_NAME}" &>/dev/null; then - pm2 restart "${PM2_APP_NAME}" - log_ok "PM2 已重启: ${PM2_APP_NAME}" - else - log_warn "进程不存在,执行完整启动 ..." - pm2_start - fi - pm2 status -} - -pm2_stop() { - if pm2 describe "${PM2_APP_NAME}" &>/dev/null; then - pm2 stop "${PM2_APP_NAME}" - log_ok "PM2 已停止: ${PM2_APP_NAME}" - else - log_warn "PM2 进程 ${PM2_APP_NAME} 不存在" - fi - pm2 status -} - -pm2_status() { - echo "" - log_info "=== PM2 状态 ===" - pm2 status || true - echo "" - log_info "=== GPU 状态 ===" - nvidia-smi 2>/dev/null || log_warn "nvidia-smi 不可用" - echo "" - log_info "=== 端口 ${GRADIO_PORT} 监听 ===" - ss -tlnp | grep ":${GRADIO_PORT}" || log_warn "端口 ${GRADIO_PORT} 未监听,服务可能未启动" - echo "" - log_info "访问地址: http://$(hostname -I | awk '{print $1}'):${GRADIO_PORT}" -} - -pm2_logs() { - pm2 logs "${PM2_APP_NAME}" --lines 80 --nostream || true -} - -# --------------------------------------------------------------------------- -# 主流程 -# --------------------------------------------------------------------------- -cmd_install() { - log_info "========== Trading Studio 一键部署开始 ==========" - log_info "安装目录: ${INSTALL_DIR}" - log_info "运行用户: root" - - install_system_deps - install_node_pm2 - deploy_code - setup_python_venv - create_runtime_dirs - set_gpu_power_limit - configure_firewall - pm2_start - - echo "" - log_ok "========== 部署完成 ==========" - echo "" - echo -e " Web 中控: ${GREEN}http://$(hostname -I | awk '{print $1}'):${GRADIO_PORT}${NC}" - echo -e " 项目目录: ${INSTALL_DIR}" - echo -e " 查看日志: ${CYAN}pm2 logs ${PM2_APP_NAME}${NC}" - echo -e " 重启服务: ${CYAN}bash ${INSTALL_DIR}/deploy.sh restart${NC}" - echo "" - log_warn "首次使用请打开 Web UI「音色锁定」上传参考人声,生成 speaker_emb.pt" -} - -cmd_update() { - log_info "========== 更新部署 ==========" - deploy_code - setup_python_venv - create_runtime_dirs - pm2_restart - log_ok "更新完成" -} - -print_usage() { - cat <&2; } + +# --------------------------------------------------------------------------- +# 前置检查 +# --------------------------------------------------------------------------- +require_root() { + if [[ "${EUID:-$(id -u)}" -ne 0 ]]; then + log_error "请使用 root 用户运行: sudo bash deploy.sh" + exit 1 + fi +} + +check_gpu() { + if command -v nvidia-smi &>/dev/null; then + log_ok "检测到 NVIDIA GPU:" + nvidia-smi --query-gpu=name,driver_version,memory.total --format=csv,noheader + else + log_warn "未检测到 nvidia-smi,Whisper/ChatTTS CUDA 加速可能不可用。" + fi +} + +set_gpu_power_limit() { + if command -v nvidia-smi &>/dev/null; then + log_info "设置 GPU 功耗上限为 ${GPU_POWER_LIMIT}W ..." + if nvidia-smi -pl "${GPU_POWER_LIMIT}" &>/dev/null; then + log_ok "GPU 功耗墙已设为 ${GPU_POWER_LIMIT}W" + else + log_warn "无法设置功耗墙,请手动执行: nvidia-smi -pl ${GPU_POWER_LIMIT}" + fi + fi +} + +# --------------------------------------------------------------------------- +# 系统依赖 +# --------------------------------------------------------------------------- +install_system_deps() { + log_info "安装系统依赖 ..." + apt-get update -qq + apt-get install -y \ + git curl wget build-essential \ + python3 python3-venv python3-dev python3-pip \ + ffmpeg libsndfile1 portaudio19-dev \ + ca-certificates gnupg + + log_ok "系统依赖安装完成" +} + +install_node_pm2() { + if command -v pm2 &>/dev/null; then + log_ok "PM2 已安装: $(pm2 -v)" + return + fi + + log_info "安装 Node.js 20 LTS 与 PM2 ..." + if ! command -v node &>/dev/null; then + curl -fsSL https://deb.nodesource.com/setup_20.x | bash - + apt-get install -y nodejs + fi + npm install -g pm2 + log_ok "PM2 安装完成: $(pm2 -v)" +} + +# --------------------------------------------------------------------------- +# 代码部署 +# --------------------------------------------------------------------------- +deploy_code() { + if [[ -d "${INSTALL_DIR}/.git" ]]; then + log_info "更新已有代码: ${INSTALL_DIR}" + git -C "${INSTALL_DIR}" pull --ff-only || { + log_warn "git pull 失败,尝试保留本地更改继续部署 ..." + } + elif [[ -d "${INSTALL_DIR}" ]]; then + log_error "${INSTALL_DIR} 已存在但不是 git 仓库,请手动处理后重试。" + exit 1 + else + log_info "克隆仓库到 ${INSTALL_DIR} ..." + git clone "${GIT_REPO}" "${INSTALL_DIR}" + fi + log_ok "代码就绪: ${INSTALL_DIR}" +} + +# --------------------------------------------------------------------------- +# Python 环境 +# --------------------------------------------------------------------------- +setup_python_venv() { + local venv_path="${INSTALL_DIR}/venv" + + if [[ ! -d "${venv_path}" ]]; then + log_info "创建 Python 虚拟环境 ..." + python3 -m venv "${venv_path}" + fi + + # shellcheck disable=SC1091 + source "${venv_path}/bin/activate" + + log_info "升级 pip ..." + pip install --upgrade pip setuptools wheel -q + + log_info "安装 PyTorch (CUDA 12.1) ..." + pip install torch torchvision torchaudio --index-url "${PYTORCH_INDEX}" -q + + log_info "安装项目依赖 ..." + pip install -r "${INSTALL_DIR}/requirements.txt" -q + + # 验证 CUDA + if python -c "import torch; assert torch.cuda.is_available()" 2>/dev/null; then + log_ok "PyTorch CUDA 可用: $(python -c 'import torch; print(torch.cuda.get_device_name(0))')" + else + log_warn "PyTorch CUDA 不可用,请检查 NVIDIA 驱动与 CUDA 运行时。" + fi + + deactivate + log_ok "Python 虚拟环境配置完成" +} + +create_runtime_dirs() { + mkdir -p "${INSTALL_DIR}/logs" + mkdir -p "${INSTALL_DIR}/uploads" + mkdir -p "${INSTALL_DIR}/outputs" + log_ok "运行时目录已创建 (logs, uploads, outputs)" +} + +# --------------------------------------------------------------------------- +# 防火墙 +# --------------------------------------------------------------------------- +configure_firewall() { + if command -v ufw &>/dev/null && ufw status | grep -q "Status: active"; then + log_info "放行 Gradio 端口 ${GRADIO_PORT} ..." + ufw allow "${GRADIO_PORT}/tcp" || true + log_ok "防火墙规则已更新" + else + log_info "ufw 未启用,跳过防火墙配置" + fi +} + +# --------------------------------------------------------------------------- +# PM2 管理 +# --------------------------------------------------------------------------- +pm2_start() { + log_info "通过 PM2 启动 Trading Studio ..." + cd "${INSTALL_DIR}" + + # 若已有同名进程则先删除再启动,避免重复 + if pm2 describe "${PM2_APP_NAME}" &>/dev/null; then + pm2 delete "${PM2_APP_NAME}" || true + fi + + pm2 start ecosystem.config.js + pm2 save + + # 配置 root 用户开机自启 + local startup_cmd + startup_cmd=$(pm2 startup systemd -u root --hp /root 2>&1 | grep "sudo env" || true) + if [[ -n "${startup_cmd}" ]]; then + eval "${startup_cmd}" || log_warn "PM2 startup 可能已配置过" + fi + pm2 save + + log_ok "PM2 启动完成" + pm2 status +} + +pm2_restart() { + cd "${INSTALL_DIR}" + if pm2 describe "${PM2_APP_NAME}" &>/dev/null; then + pm2 restart "${PM2_APP_NAME}" + log_ok "PM2 已重启: ${PM2_APP_NAME}" + else + log_warn "进程不存在,执行完整启动 ..." + pm2_start + fi + pm2 status +} + +pm2_stop() { + if pm2 describe "${PM2_APP_NAME}" &>/dev/null; then + pm2 stop "${PM2_APP_NAME}" + log_ok "PM2 已停止: ${PM2_APP_NAME}" + else + log_warn "PM2 进程 ${PM2_APP_NAME} 不存在" + fi + pm2 status +} + +pm2_status() { + echo "" + log_info "=== PM2 状态 ===" + pm2 status || true + echo "" + log_info "=== GPU 状态 ===" + nvidia-smi 2>/dev/null || log_warn "nvidia-smi 不可用" + echo "" + log_info "=== 端口 ${GRADIO_PORT} 监听 ===" + ss -tlnp | grep ":${GRADIO_PORT}" || log_warn "端口 ${GRADIO_PORT} 未监听,服务可能未启动" + echo "" + log_info "访问地址: http://$(hostname -I | awk '{print $1}'):${GRADIO_PORT}" +} + +pm2_logs() { + pm2 logs "${PM2_APP_NAME}" --lines 80 --nostream || true +} + +# --------------------------------------------------------------------------- +# 主流程 +# --------------------------------------------------------------------------- +cmd_install() { + log_info "========== Trading Studio 一键部署开始 ==========" + log_info "安装目录: ${INSTALL_DIR}" + log_info "运行用户: root" + + install_system_deps + install_node_pm2 + deploy_code + setup_python_venv + create_runtime_dirs + set_gpu_power_limit + configure_firewall + pm2_start + + echo "" + log_ok "========== 部署完成 ==========" + echo "" + echo -e " Web 中控: ${GREEN}http://$(hostname -I | awk '{print $1}'):${GRADIO_PORT}${NC}" + echo -e " 项目目录: ${INSTALL_DIR}" + echo -e " 查看日志: ${CYAN}pm2 logs ${PM2_APP_NAME}${NC}" + echo -e " 重启服务: ${CYAN}bash ${INSTALL_DIR}/deploy.sh restart${NC}" + echo "" + log_warn "首次使用请打开 Web UI「音色锁定」上传参考人声,生成 speaker_emb.pt" +} + +cmd_update() { + log_info "========== 更新部署 ==========" + deploy_code + setup_python_venv + create_runtime_dirs + pm2_restart + log_ok "更新完成" +} + +print_usage() { + cat <