Add one-click deploy script for /opt production setup with PM2.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -2,12 +2,14 @@
|
|||||||
|
|
||||||
本文档面向 **Ubuntu 物理服务器**(搭载 RTX 3060 Ti,已锁定 120W 功耗墙)的完整环境配置与 PM2 常驻部署流程。适用于首次安装或迁移重装场景。
|
本文档面向 **Ubuntu 物理服务器**(搭载 RTX 3060 Ti,已锁定 120W 功耗墙)的完整环境配置与 PM2 常驻部署流程。适用于首次安装或迁移重装场景。
|
||||||
|
|
||||||
|
**标准安装路径:** `/opt/Trading_Studio`(root 用户)
|
||||||
**Git 仓库:** https://git.bz121.com/dekun/Trading_Studio.git
|
**Git 仓库:** https://git.bz121.com/dekun/Trading_Studio.git
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 目录
|
## 目录
|
||||||
|
|
||||||
|
0. [**一键部署(推荐)**](#0-一键部署推荐)
|
||||||
1. [硬件与系统前提](#1-硬件与系统前提)
|
1. [硬件与系统前提](#1-硬件与系统前提)
|
||||||
2. [3060 Ti 120W 功耗墙配置](#2-3060-ti-120w-功耗墙配置)
|
2. [3060 Ti 120W 功耗墙配置](#2-3060-ti-120w-功耗墙配置)
|
||||||
3. [NVIDIA 驱动与 CUDA](#3-nvidia-驱动与-cuda)
|
3. [NVIDIA 驱动与 CUDA](#3-nvidia-驱动与-cuda)
|
||||||
@@ -21,6 +23,112 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## 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. 硬件与系统前提
|
## 1. 硬件与系统前提
|
||||||
|
|
||||||
| 项目 | 要求 |
|
| 项目 | 要求 |
|
||||||
@@ -130,7 +238,7 @@ PyTorch cu121 wheel 通常自带运行时库。若 Whisper 报 cuDNN 错误:
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 克隆项目
|
# 克隆项目
|
||||||
cd ~
|
cd /opt
|
||||||
git clone https://git.bz121.com/dekun/Trading_Studio.git
|
git clone https://git.bz121.com/dekun/Trading_Studio.git
|
||||||
cd Trading_Studio
|
cd Trading_Studio
|
||||||
|
|
||||||
@@ -184,7 +292,7 @@ GPU: NVIDIA GeForce RTX 3060 Ti
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
source venv/bin/activate
|
source venv/bin/activate
|
||||||
cd ~/Trading_Studio
|
cd /opt/Trading_Studio
|
||||||
|
|
||||||
# 安装其余依赖
|
# 安装其余依赖
|
||||||
pip install -r requirements.txt
|
pip install -r requirements.txt
|
||||||
@@ -270,7 +378,7 @@ curl http://192.168.8.64:11434/api/chat -d '{
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
source venv/bin/activate
|
source venv/bin/activate
|
||||||
cd ~/Trading_Studio
|
cd /opt/Trading_Studio
|
||||||
|
|
||||||
# 前台启动(调试)
|
# 前台启动(调试)
|
||||||
python app.py
|
python app.py
|
||||||
@@ -341,7 +449,7 @@ module.exports = {
|
|||||||
启动:
|
启动:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd ~/Trading_Studio
|
cd /opt/Trading_Studio
|
||||||
mkdir -p logs
|
mkdir -p logs
|
||||||
|
|
||||||
pm2 start ecosystem.config.js
|
pm2 start ecosystem.config.js
|
||||||
@@ -349,10 +457,12 @@ pm2 status
|
|||||||
pm2 logs trading_studio --lines 50
|
pm2 logs trading_studio --lines 50
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> **推荐:** 直接使用 `bash deploy.sh` 一键完成上述步骤,见 [第 0 节](#0-一键部署推荐)。
|
||||||
|
|
||||||
### 9.3 方式 B:直接命令行
|
### 9.3 方式 B:直接命令行
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd ~/Trading_Studio
|
cd /opt/Trading_Studio
|
||||||
|
|
||||||
pm2 start app.py \
|
pm2 start app.py \
|
||||||
--name "trading_studio" \
|
--name "trading_studio" \
|
||||||
@@ -382,7 +492,14 @@ pm2 monit # 实时监控 CPU/内存
|
|||||||
### 9.6 更新代码后重新部署
|
### 9.6 更新代码后重新部署
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd ~/Trading_Studio
|
cd /opt/Trading_Studio
|
||||||
|
bash deploy.sh update
|
||||||
|
```
|
||||||
|
|
||||||
|
或手动:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /opt/Trading_Studio
|
||||||
git pull
|
git pull
|
||||||
source venv/bin/activate
|
source venv/bin/activate
|
||||||
pip install -r requirements.txt # 若有新依赖
|
pip install -r requirements.txt # 若有新依赖
|
||||||
@@ -395,10 +512,10 @@ pm2 restart trading_studio
|
|||||||
|
|
||||||
### 10.1 迁移到新机器
|
### 10.1 迁移到新机器
|
||||||
|
|
||||||
1. 复制 `speaker_emb.pt`(音色文件,在 `.gitignore` 中,需手动备份)
|
1. 备份 `/opt/Trading_Studio/speaker_emb.pt`(音色文件,不入 Git)
|
||||||
2. 新机器按本文档完整部署
|
2. 新机器执行 `bash deploy.sh` 一键部署
|
||||||
3. 将 `speaker_emb.pt` 放回项目根目录
|
3. 将 `speaker_emb.pt` 复制回 `/opt/Trading_Studio/`
|
||||||
4. `pm2 restart trading_studio`
|
4. `bash deploy.sh restart`
|
||||||
|
|
||||||
### 10.2 CUDA / 显存问题
|
### 10.2 CUDA / 显存问题
|
||||||
|
|
||||||
|
|||||||
@@ -52,20 +52,36 @@ Trading Studio 是一套运行在 Ubuntu 物理服务器(RTX 3060 Ti)上的
|
|||||||
|
|
||||||
> 完整环境配置请参阅 [DEPLOY.md](./DEPLOY.md)
|
> 完整环境配置请参阅 [DEPLOY.md](./DEPLOY.md)
|
||||||
|
|
||||||
```bash
|
### 一键部署(生产环境推荐)
|
||||||
# 1. 克隆仓库
|
|
||||||
git clone https://git.bz121.com/dekun/Trading_Studio.git
|
|
||||||
cd Trading_Studio
|
|
||||||
|
|
||||||
# 2. 创建虚拟环境并安装依赖(详见 DEPLOY.md)
|
以 **root** 用户部署到 `/opt/Trading_Studio` 并由 PM2 常驻:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo -i
|
||||||
|
git clone https://git.bz121.com/dekun/Trading_Studio.git /opt/Trading_Studio
|
||||||
|
cd /opt/Trading_Studio
|
||||||
|
chmod +x deploy.sh
|
||||||
|
bash deploy.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
浏览器访问:`http://<服务器IP>:5683`
|
||||||
|
|
||||||
|
日常更新:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /opt/Trading_Studio && bash deploy.sh update
|
||||||
|
```
|
||||||
|
|
||||||
|
### 手动部署(开发调试)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://git.bz121.com/dekun/Trading_Studio.git /opt/Trading_Studio
|
||||||
|
cd /opt/Trading_Studio
|
||||||
python3 -m venv venv
|
python3 -m venv venv
|
||||||
source venv/bin/activate
|
source venv/bin/activate
|
||||||
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121
|
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121
|
||||||
pip install -r requirements.txt
|
pip install -r requirements.txt
|
||||||
|
|
||||||
# 3. 启动中控
|
|
||||||
python app.py
|
python app.py
|
||||||
# 浏览器访问: http://<服务器IP>:5683
|
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -108,18 +124,21 @@ python app.py
|
|||||||
|
|
||||||
## PM2 守护运行
|
## PM2 守护运行
|
||||||
|
|
||||||
```bash
|
标准路径 `/opt/Trading_Studio`,root 用户:
|
||||||
# 方式 1:ecosystem 配置
|
|
||||||
pm2 start ecosystem.config.js
|
|
||||||
|
|
||||||
# 方式 2:直接命令
|
```bash
|
||||||
pm2 start app.py --name "trading_studio" --interpreter ./venv/bin/python
|
# 一键部署 + PM2 启动(推荐)
|
||||||
|
cd /opt/Trading_Studio && bash deploy.sh
|
||||||
|
|
||||||
|
# 或手动 PM2
|
||||||
|
pm2 start ecosystem.config.js
|
||||||
|
|
||||||
# 常用管理
|
# 常用管理
|
||||||
pm2 status
|
pm2 status
|
||||||
pm2 logs trading_studio
|
pm2 logs trading_studio
|
||||||
pm2 restart trading_studio
|
bash deploy.sh restart # 重启
|
||||||
pm2 save && pm2 startup # 开机自启
|
bash deploy.sh update # 拉代码 + 更新依赖 + 重启
|
||||||
|
pm2 save && pm2 startup # 开机自启(deploy.sh 已自动配置)
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -150,6 +169,7 @@ outputs/
|
|||||||
|
|
||||||
```
|
```
|
||||||
Trading_Studio/
|
Trading_Studio/
|
||||||
|
├── deploy.sh # 一键部署脚本(/opt + PM2)
|
||||||
├── app.py # Gradio 主入口
|
├── app.py # Gradio 主入口
|
||||||
├── config.py # 全局配置
|
├── config.py # 全局配置
|
||||||
├── whisper_service.py # Whisper CUDA 识别
|
├── whisper_service.py # Whisper CUDA 识别
|
||||||
@@ -158,13 +178,15 @@ Trading_Studio/
|
|||||||
├── ecosystem.config.js # PM2 守护配置
|
├── ecosystem.config.js # PM2 守护配置
|
||||||
├── requirements.txt # Python 依赖
|
├── requirements.txt # Python 依赖
|
||||||
├── README.md # 本文件
|
├── README.md # 本文件
|
||||||
├── DEPLOY.md # 部署指南
|
├── DEPLOY.md # 部署指南(含一键部署教程)
|
||||||
├── .gitignore
|
├── .gitignore
|
||||||
├── speaker_emb.pt # 音色文件(运行时生成,不入库)
|
├── speaker_emb.pt # 音色文件(运行时生成,不入库)
|
||||||
├── uploads/ # 上传临时目录
|
├── uploads/ # 上传临时目录
|
||||||
└── outputs/ # 合成 wav 输出
|
└── outputs/ # 合成 wav 输出
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**生产标准路径:** `/opt/Trading_Studio`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 硬件要求
|
## 硬件要求
|
||||||
|
|||||||
@@ -47,7 +47,10 @@ WHISPER_LANGUAGE = "zh"
|
|||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# ChatTTS 配置
|
# ChatTTS 配置
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# 项目根目录
|
# 标准生产安装路径(/opt,root 部署)
|
||||||
|
INSTALL_DIR = Path("/opt/Trading_Studio")
|
||||||
|
|
||||||
|
# 项目根目录(开发/生产均自适应,以实际 app.py 所在目录为准)
|
||||||
BASE_DIR = Path(__file__).resolve().parent
|
BASE_DIR = Path(__file__).resolve().parent
|
||||||
|
|
||||||
# 固定音色 Embedding 存储路径
|
# 固定音色 Embedding 存储路径
|
||||||
|
|||||||
@@ -0,0 +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 <<EOF
|
||||||
|
Trading Studio 一键部署脚本
|
||||||
|
|
||||||
|
用法:
|
||||||
|
sudo bash deploy.sh [命令]
|
||||||
|
|
||||||
|
命令:
|
||||||
|
(无参数) 首次完整部署到 /opt/Trading_Studio 并由 PM2 启动
|
||||||
|
install 同上
|
||||||
|
update 拉取最新代码、更新 Python 依赖、重启 PM2
|
||||||
|
restart 重启 PM2 进程
|
||||||
|
stop 停止 PM2 进程
|
||||||
|
status 查看 PM2 / GPU / 端口状态
|
||||||
|
logs 查看 PM2 最近日志
|
||||||
|
help 显示本帮助
|
||||||
|
|
||||||
|
示例:
|
||||||
|
cd /opt/Trading_Studio && sudo bash deploy.sh update
|
||||||
|
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
require_root
|
||||||
|
|
||||||
|
local cmd="${1:-install}"
|
||||||
|
|
||||||
|
case "${cmd}" in
|
||||||
|
install|"")
|
||||||
|
check_gpu
|
||||||
|
cmd_install
|
||||||
|
;;
|
||||||
|
update)
|
||||||
|
check_gpu
|
||||||
|
cmd_update
|
||||||
|
;;
|
||||||
|
restart)
|
||||||
|
pm2_restart
|
||||||
|
;;
|
||||||
|
stop)
|
||||||
|
pm2_stop
|
||||||
|
;;
|
||||||
|
status)
|
||||||
|
pm2_status
|
||||||
|
;;
|
||||||
|
logs)
|
||||||
|
pm2_logs
|
||||||
|
;;
|
||||||
|
help|-h|--help)
|
||||||
|
print_usage
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
log_error "未知命令: ${cmd}"
|
||||||
|
print_usage
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
+10
-5
@@ -1,14 +1,19 @@
|
|||||||
/**
|
/**
|
||||||
* PM2 进程守护配置
|
* PM2 进程守护配置
|
||||||
|
* 标准安装路径: /opt/Trading_Studio
|
||||||
* 用法: pm2 start ecosystem.config.js
|
* 用法: pm2 start ecosystem.config.js
|
||||||
*/
|
*/
|
||||||
|
const path = require("path");
|
||||||
|
|
||||||
|
const APP_DIR = __dirname;
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
apps: [
|
apps: [
|
||||||
{
|
{
|
||||||
name: "trading_studio",
|
name: "trading_studio",
|
||||||
script: "app.py",
|
script: path.join(APP_DIR, "app.py"),
|
||||||
interpreter: "./venv/bin/python",
|
interpreter: path.join(APP_DIR, "venv/bin/python"),
|
||||||
cwd: __dirname,
|
cwd: APP_DIR,
|
||||||
instances: 1,
|
instances: 1,
|
||||||
autorestart: true,
|
autorestart: true,
|
||||||
watch: false,
|
watch: false,
|
||||||
@@ -17,8 +22,8 @@ module.exports = {
|
|||||||
PYTHONUNBUFFERED: "1",
|
PYTHONUNBUFFERED: "1",
|
||||||
CUDA_VISIBLE_DEVICES: "0",
|
CUDA_VISIBLE_DEVICES: "0",
|
||||||
},
|
},
|
||||||
error_file: "./logs/pm2-error.log",
|
error_file: path.join(APP_DIR, "logs/pm2-error.log"),
|
||||||
out_file: "./logs/pm2-out.log",
|
out_file: path.join(APP_DIR, "logs/pm2-out.log"),
|
||||||
log_date_format: "YYYY-MM-DD HH:mm:ss",
|
log_date_format: "YYYY-MM-DD HH:mm:ss",
|
||||||
merge_logs: true,
|
merge_logs: true,
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user