Co-authored-by: Cursor <cursoragent@cursor.com>
20 KiB
部署文档
国内期货 · 交易复盘系统 — Ubuntu 服务器部署、更新与运维说明。
代码发布铁律(强制,不容置疑)
所有代码变更必须且只能按以下三步执行,不得跳过、不得变通:
| 步骤 | 在哪里 | 做什么 |
|---|---|---|
| 1. 本地修改 | 开发机 / 本仓库工作区 | 改代码、自测 |
| 2. 提交仓库 | git.bz121.com |
git add → git commit → git push origin main(或约定分支) |
| 3. 更新服务器 | /opt/qihuo |
仅 git fetch + git reset --hard origin/main(或 git pull)→ 依赖/迁移 → pm2 restart |
严禁事项
- 禁止 用
scp、rsync、SFTP、手工复制等方式把.py/.js/.html/ 模板 / 静态资源 直接覆盖 到服务器。 - 禁止 在服务器上
vim改业务代码后长期不提交仓库(.env、日志、上传文件除外)。 - 禁止 「服务器上先改一版、本地以后再补提交」——服务器代码必须与远端 Git 完全一致。
违反上述规则会导致:git pull 冲突、Web 与 Worker 版本不一致、问题无法复现、回滚困难。一律视为部署事故。
服务器唯一合法更新命令
代码已推送到远端后,在服务器执行:
cd /opt/qihuo
git fetch origin
git reset --hard origin/main
source venv/bin/activate
pip install -r requirements.txt
python scripts/run_schema_migrate.py
pm2 restart ecosystem.config.cjs --update-env
pm2 save
或使用 bash deploy.sh(内部同样通过 Git 拉取,见下文)。
数据与配置(不受 Git 管理)
以下文件 不 随 git pull 更新,卸载/重装时须 单独备份与恢复:
/opt/qihuo/.env/opt/qihuo/futures.db(SQLite)或 PostgreSQL 数据/opt/qihuo/uploads//opt/qihuo/backups/(若有)
部署概要
| 项目 | 默认值 |
|---|---|
| 部署目录 | /opt/qihuo |
| 运行用户 | root(与 deploy.sh / PM2 配置一致) |
| Web 端口 | 6600(对外) |
| CTP Worker 端口 | 6601(仅 127.0.0.1,Web 进程 IPC 调用,勿对外开放) |
| 进程管理 | PM2:qihuo(Flask Web)+ qihuo-ctp(CTP / vn.py 独立进程) |
| 数据库 | 生产推荐 PostgreSQL(见 POSTGRES.md);未配置 DATABASE_URL 时使用 SQLite futures.db |
| 仓库 | https://git.bz121.com/dekun/qihuo.git |
进程架构(2026-03 起)
| PM2 应用 | 角色 | 说明 |
|---|---|---|
qihuo |
Web(QIHUO_CTP_ROLE=client) |
Flask、页面、API、数据库;通过 HTTP 调用本机 Worker |
qihuo-ctp |
Worker(QIHUO_CTP_ROLE=worker) |
唯一 加载 vn.py / vnpy_ctp;CTP 连接、报单、持仓回调、止盈止损 tick、滚仓监控 |
Web 进程崩溃或重启 不会 直接带走 CTP 原生连接;Worker 重启后 Web 会自动通过 IPC 恢复读写。两个进程的 Token 须一致(见 ecosystem.config.cjs 中 QIHUO_CTP_WORKER_TOKEN)。
环境要求
- 系统:Ubuntu 20.04+(推荐)
- Python:3.10+(vnpy_ctp 要求 ≥3.10)
- Node.js + PM2:进程守护与开机自启
- 编译工具(安装 vnpy_ctp 时需要):
build-essential、python3-dev、pkg-config - 网络:
hq.sinajs.cn(新浪行情)- 企业微信 API(若启用推送)
git.bz121.com(拉取代码)pypi.org(pip 安装依赖)- SimNow / 期货公司 CTP 前置地址(下单与持仓,见下文)
一键部署(推荐)
以 root 登录服务器后执行:
cd /opt/qihuo
# 若目录不存在,先克隆:
# git clone https://git.bz121.com/dekun/qihuo.git /opt/qihuo
bash deploy.sh
deploy.sh 会自动完成:
- 安装系统依赖:
python3、git、build-essential、python3-dev、pkg-config、locales、netcat-openbsd、pm2 - 时区设为
Asia/Shanghai(与 SimNow 交易时段一致) - locale:生成
zh_CN.GB18030、zh_CN.UTF-8(CTP 登录必需,缺则进程崩溃) git pull或git clone到/opt/qihuo- 创建/保留虚拟环境
venv,pip install -r requirements.txt,验证vnpy_ctp - 首次生成
.env,并补全SIMNOW_ENV=实盘、CTP_AUTO_RECONNECT=true等缺项 - 自动探测 SimNow 前置(
nc测端口),写入可用的SIMNOW_TD/MD_ADDRESS(优先182.254.243.31,其次180.168.146.187) - 若已配置 SimNow 账号,运行
scripts/test_simnow.py验证连接 pm2 restart ecosystem.config.cjs --update-env或首次pm2 start ecosystem.config.cjs,并pm2 save(同时启动qihuo与qihuo-ctp)
部署完成后访问:http://<服务器IP>:6600
PostgreSQL 生产库(推荐)
消除 SQLite 并发 database is locked,一键安装 PostgreSQL 并迁移:
cd /opt/qihuo
git pull
# 新装 PostgreSQL + 空库
sudo bash scripts/deploy_postgres.sh
# 从现有 futures.db 迁移
MIGRATE_SQLITE=1 sudo bash scripts/deploy_postgres.sh
完整说明、手动步骤、备份恢复见 POSTGRES.md。
再次部署只需
cd /opt/qihuo && bash deploy.sh,无需手工装 locale 或改前置地址。
服务器卸载与全新部署(Git 唯一来源)
当服务器代码被 SCP 弄乱、版本不可信、或需要与仓库 完全对齐 时,按本节 卸载后重装。全程 只 通过 Git 获取代码,不得 SCP 复制业务文件。
1. 备份(必做)
# 在服务器上
cp /opt/qihuo/.env /root/qihuo.env.bak
# SQLite
cp /opt/qihuo/futures.db /root/futures.db.bak 2>/dev/null || true
# PostgreSQL 见 POSTGRES.md 备份命令
tar czf /root/qihuo_uploads.bak.tar.gz -C /opt/qihuo uploads 2>/dev/null || true
2. 卸载 PM2 与代码目录
pm2 stop qihuo qihuo-ctp 2>/dev/null || true
pm2 delete qihuo qihuo-ctp 2>/dev/null || true
pm2 save
rm -rf /opt/qihuo
不删除
/root/qihuo.env.bak、/root/futures.db.bak等备份。
3. 从 Git 全新克隆并部署
git clone https://git.bz121.com/dekun/qihuo.git /opt/qihuo
cd /opt/qihuo
cp /root/qihuo.env.bak .env
# SQLite 恢复(若使用)
cp /root/futures.db.bak futures.db 2>/dev/null || true
bash deploy.sh
4. 验收
cd /opt/qihuo && git log -1 --oneline # 须与远端 main 最新提交一致
pm2 status # qihuo、qihuo-ctp 均为 online
浏览器访问 http://<服务器IP>:6600 登录验证。
此后所有更新 只 走上文「代码发布铁律」三步,禁止 再使用 SCP 更新代码。
手动部署
1. 安装系统依赖
apt update
apt install -y python3 python3-venv python3-pip python3-dev pkg-config git nodejs npm build-essential locales netcat-openbsd
timedatectl set-timezone Asia/Shanghai
sed -i '/^# zh_CN.GB18030/s/^# //' /etc/locale.gen
sed -i '/^# zh_CN.UTF-8/s/^# //' /etc/locale.gen
locale-gen zh_CN.GB18030 zh_CN.UTF-8
update-locale LANG=zh_CN.UTF-8 LC_ALL=zh_CN.UTF-8
npm install -g pm2
build-essential、python3-dev、pkg-config 用于编译安装 vnpy_ctp(CTP 网关)。Meson 通过 pkg-config 查找 Python 头文件;缺 pkg-config 时会报 Python dependency not found。
2. 克隆代码
git clone https://git.bz121.com/dekun/qihuo.git /opt/qihuo
cd /opt/qihuo
3. Python 虚拟环境与依赖
python3 -m venv venv
source venv/bin/activate
pip install --upgrade pip
pip install -r requirements.txt
依赖已包含 vnpy、vnpy_ctp(CTP 报单)、akshare(手续费同步)。安装完成后可验证:
python -c "from vnpy_ctp import CtpGateway; print('vnpy_ctp OK')"
若提示找不到模块,查看本文「CTP / vnpy 故障排查」一节。
cp .env.example .env
nano .env
| 变量 | 说明 |
|---|---|
HOST |
监听地址,默认 0.0.0.0 |
PORT |
端口,默认 6600 |
SECRET_KEY |
Flask Session 密钥,务必随机 |
ADMIN_USERNAME |
初始管理员用户名 |
ADMIN_PASSWORD |
初始管理员密码(仅首次建库生效) |
ADMIN_SYNC_FROM_ENV |
true 时重启可从 .env 同步账号密码 |
WECHAT_WEBHOOK |
企业微信机器人地址(可选) |
QUOTE_SOURCE |
sina(默认)/ ths / auto |
THS_REFRESH_TOKEN |
同花顺 iFinD token(机构用户) |
SIMNOW_USER |
SimNow 仿真账号(模拟盘必填) |
SIMNOW_PASSWORD |
SimNow 密码 |
SIMNOW_TD_ADDRESS |
SimNow 交易前置(以官网最新为准) |
SIMNOW_MD_ADDRESS |
SimNow 行情前置 |
CTP_LIVE_* |
期货公司实盘 CTP(后期接入,见 .env.example) |
TRADING_MODE |
simulation(SimNow)/ live(实盘) |
QIHUO_CTP_WORKER_TOKEN |
Web ↔ Worker IPC 鉴权(默认见 ecosystem.config.cjs,生产建议改随机串并保持两进程一致) |
QIHUO_CTP_WORKER_URL |
Web 侧 Worker 地址,默认 http://127.0.0.1:6601 |
DATABASE_URL |
PostgreSQL 连接串(可选,见 POSTGRES.md) |
示例:
HOST=0.0.0.0
PORT=6600
SECRET_KEY=请替换为随机长字符串
ADMIN_USERNAME=admin
ADMIN_PASSWORD=你的强密码
ADMIN_SYNC_FROM_ENV=false
WECHAT_WEBHOOK=
QUOTE_SOURCE=sina
# —— SimNow 模拟盘(注册步骤见 docs/SIMNOW.md)——
SIMNOW_USER=你的SimNow账号
SIMNOW_PASSWORD=你的密码
SIMNOW_BROKER_ID=9999
SIMNOW_TD_ADDRESS=tcp://180.168.146.187:10201
SIMNOW_MD_ADDRESS=tcp://180.168.146.187:10211
SIMNOW_APP_ID=simnow_client_test
SIMNOW_AUTH_CODE=0000000000000000
SIMNOW_ENV=实盘
TRADING_MODE=simulation
SimNow 前置地址会随官网更新,部署前请到 SimNow 官网 核对 7×24 或交易时段地址。
6. PM2 启动
cd /opt/qihuo
pm2 start ecosystem.config.cjs # 启动 qihuo + qihuo-ctp
pm2 save
pm2 startup # 按提示执行命令,实现开机自启
确认两个进程均为 online:
pm2 status
# 应看到 qihuo 与 qihuo-ctp
7. 创建日志目录(若不存在)
mkdir -p /opt/qihuo/logs /opt/qihuo/uploads
更新部署
强制流程:本地修改 →
git push→ 服务器git fetch && git reset --hard origin/main→ 迁移 →pm2 restart。
禁止 SCP 复制代码。 详见上文 代码发布铁律。
代码已推送后,在服务器执行:
cd /opt/qihuo
git fetch origin
git reset --hard origin/main
source venv/bin/activate
pip install -r requirements.txt
python scripts/run_schema_migrate.py
pm2 restart ecosystem.config.cjs --update-env
pm2 save
须 同时重启
qihuo与qihuo-ctp。仅pm2 restart qihuo会导致 Web 与 Worker 代码/协议不一致。
若服务器曾用 SCP 覆盖文件导致 git pull 冲突,用 git reset --hard origin/main 与远端对齐。
若 vnpy_ctp 安装失败(常见于缺少编译环境):
apt install -y build-essential python3-dev pkg-config
source venv/bin/activate
pip install --no-cache-dir vnpy vnpy_ctp
pm2 restart ecosystem.config.cjs --update-env
应用启动时会自动执行 SQLite 表结构迁移(ALTER TABLE 容错),一般无需手工改库。
首次启用 CTP 下单
- 浏览器登录 → 系统设置 确认 模拟盘 · SimNow
- 确认
pm2 status中qihuo-ctp为 online - 打开 下单监控 页 → 点击 连接 CTP(或由后台自动重连)
- 连接成功后:权益来自柜台、显示 CTP 持仓、可报单与可开仓品种筛选
CTP 连接与重连在 qihuo-ctp Worker 内执行;页面仅轮询状态,切换页面不会重复发起连接。
详见 TRADING.md。
PM2 常用命令
pm2 status # 查看 qihuo / qihuo-ctp 状态
pm2 logs qihuo # Web 日志
pm2 logs qihuo-ctp # CTP Worker 日志
pm2 logs qihuo --lines 100
pm2 restart ecosystem.config.cjs --update-env # 同时重启两个进程(推荐)
pm2 restart qihuo # 仅重启 Web
pm2 restart qihuo-ctp # 仅重启 CTP Worker(Web 应仍可访问)
pm2 stop qihuo # 停止 Web
pm2 delete qihuo # 删除 Web 进程
pm2 save # 保存进程列表
日志文件:
/opt/qihuo/logs/pm2-out.log、pm2-error.log— Web(qihuo)/opt/qihuo/logs/pm2-ctp-out.log、pm2-ctp-error.log— CTP Worker(qihuo-ctp)
本地开发
git clone https://git.bz121.com/dekun/qihuo.git
cd qihuo
python3 -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install -r requirements.txt
cp .env.example .env
python app.py
浏览器访问:http://127.0.0.1:6600
账号与密码
| 场景 | 操作 |
|---|---|
| 首次部署 | .env 中设置 ADMIN_USERNAME / ADMIN_PASSWORD 后启动 |
已部署后改 .env 密码 |
设 ADMIN_SYNC_FROM_ENV=true,pm2 restart ecosystem.config.cjs --update-env |
| 网页改密码 | 登录 → 系统设置 |
| 忘记密码 | cd /opt/qihuo && source venv/bin/activate && python reset_admin.py |
账号数据在 futures.db 的 settings 表,不会仅因改 .env 自动更新(除非开启 ADMIN_SYNC_FROM_ENV)。
数据库与数据文件
| 路径 | 说明 |
|---|---|
/opt/qihuo/futures.db |
主数据库 |
/opt/qihuo/uploads/ |
复盘截图、自动 K 线图 |
/opt/qihuo/data/fee_rates.json |
默认手续费表(可重载) |
/root/qihuo_backup/ |
系统自动备份目录(.tar.gz) |
自动备份(推荐)
系统设置 → 数据备份与恢复:
- 默认每天 03:00 自动备份到
/root/qihuo_backup - 含
futures.db与uploads/,可在其他服务器恢复 - 设置页可立即备份、下载历史压缩包
完整说明见 BACKUP.md。
手工备份(备选)
cp /opt/qihuo/futures.db /opt/qihuo/futures.db.bak.$(date +%Y%m%d)
手工补列(极少需要)
若极老版本库缺少字段,可对照报错执行(新版本启动会自动迁移):
sqlite3 /opt/qihuo/futures.db "ALTER TABLE key_monitors ADD COLUMN sina_code TEXT;"
Nginx 反向代理(可选)
将 6600 反代到 80/443,并配置 HTTPS:
server {
listen 80;
server_name your.domain.com;
location / {
proxy_pass http://127.0.0.1:6600;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
防火墙
若使用 ufw,开放端口:
ufw allow 6600/tcp
# 或使用 Nginx 时只开放 80/443
故障排查
| 现象 | 可能原因 | 处理 |
|---|---|---|
| 无法访问 6600 | 服务未启动 / 防火墙 | pm2 status、pm2 logs qihuo |
qihuo-ctp 不在线 / 反复重启 |
vnpy 崩溃、SimNow 前置不可达、locale 缺失 | pm2 logs qihuo-ctp --lines 200;核对 SimNow 前置与 zh_CN.GB18030 |
| 页面显示 CTP 未连接但 Worker 正常 | Web 与 Worker Token 不一致 | 检查 ecosystem.config.cjs 两进程 QIHUO_CTP_WORKER_TOKEN 相同后重启 |
API 报 CTP worker unavailable |
Worker 未启动或 6601 不可达 | curl -s http://127.0.0.1:6601/health;pm2 restart qihuo-ctp |
| 登录失败 | 密码未同步 | 网页改密或 reset_admin.py |
现价一直 -- |
新浪网络不可达 | 检查服务器能否访问 hq.sinajs.cn |
| 关键位 500 | 缺 sina_code 列 |
git pull 重启;或手工 ALTER TABLE |
| K 线生成失败 | matplotlib 未装 | pip install matplotlib==3.9.2 |
| 手续费同步失败 | akshare 异常 | 使用「重载 JSON」或检查 akshare |
| 未安装 vnpy / vnpy_ctp | 依赖未装或编译失败 | 见下方「CTP / vnpy 故障排查」 |
| CTP 连接超时 | SimNow 地址/账号/非交易时段 | 核对 .env 与 SimNow 官网前置 |
| 下单监控无持仓 | 未连接 CTP 或确实无仓 | 先点「连接 CTP」 |
Could not resolve host |
服务器 DNS 故障 | 配置 systemd-resolved 公共 DNS,见下方 |
database is locked |
SQLite 并发 | 推荐改 PostgreSQL:MIGRATE_SQLITE=1 bash scripts/deploy_postgres.sh,见 POSTGRES.md |
git pull 冲突 |
曾用 SCP 覆盖文件(禁止) | 按 服务器卸载与全新部署 或 git reset --hard origin/main 与远端对齐 |
查看应用是否在监听:
ss -tlnp | grep 6600
DNS 无法解析(git / curl 均失败)
若 curl cip.cc 或 git pull 报 Could not resolve host:
mkdir -p /etc/systemd/resolved.conf.d
cat > /etc/systemd/resolved.conf.d/dns.conf <<'EOF'
[Resolve]
DNS=223.5.5.5 8.8.8.8
FallbackDNS=1.1.1.1
EOF
systemctl restart systemd-resolved
resolvectl flush-caches
验证:resolvectl query git.bz121.com、curl cip.cc
页面提示 「未安装 vnpy / vnpy_ctp」 表示 Python 环境未成功安装 CTP 网关,下单与柜台持仓不可用(看盘、策略、复盘仍可用)。
1. 安装依赖
cd /opt/qihuo
source venv/bin/activate
apt install -y build-essential python3-dev pkg-config # 首次需要
pip install -r requirements.txt
python -c "from vnpy_ctp import CtpGateway; print('OK')"
pm2 restart ecosystem.config.cjs --update-env
2. 配置 SimNow(.env)
注册与查投资者代码见 SIMNOW.md。填写 SIMNOW_USER(投资者代码)、SIMNOW_PASSWORD,前置地址以 SimNow 官网为准。
3. 连接
登录系统 → 下单监控 → 连接 CTP。成功则顶栏显示「CTP 已连接」,权益变为 SimNow 账户资金。
4. 常见错误
| 日志/现象 | 处理 |
|---|---|
pip install vnpy_ctp 编译失败 / Python dependency not found |
安装 build-essential python3-dev pkg-config 后重试 |
| CTP 连接超时 | 检查前置 IP、端口、SimNow 是否维护、是否在允许连接时段 |
连接后立即崩溃 locale::facet::_S_create_c_locale |
CTP 需 zh_CN.GB18030:sed -i '/^# zh_CN.GB18030/s/^# //' /etc/locale.gen && locale-gen zh_CN.GB18030,再 pm2 restart ecosystem.config.cjs --update-env |
服务器 180.168.146.187 超时 |
换 SimNow 备用前置 182.254.243.31:30001/30011(见 SIMNOW.md) |
| 已连接但下单拒单 | 检查合约代码、价格精度、是否有足够保证金 |
安全建议
- 部署后立即修改默认密码
- 勿将
.env、futures.db提交到公开仓库 - 生产环境使用 HTTPS + 限制访问 IP
- 定期备份:系统设置页自动备份至
/root/qihuo_backup,或见 BACKUP.md
目录结构(部署后)
/opt/qihuo/
├── app.py
├── vnpy_bridge.py # CTP 桥接(Web=IPC 代理,Worker=原生 vn.py)
├── ctp_ipc_client.py # Web → Worker HTTP 客户端
├── ctp_worker.py # 独立 CTP Worker 入口(PM2: qihuo-ctp)
├── recommend_store.py # 可开仓品种缓存
├── recommend_stream.py # 可开仓品种 SSE 推送
├── venv/
├── futures.db
├── .env
├── logs/
│ ├── pm2-out.log
│ ├── pm2-error.log
│ ├── pm2-ctp-out.log
│ └── pm2-ctp-error.log
├── uploads/
├── data/fee_rates.json
├── ecosystem.config.cjs # PM2:qihuo + qihuo-ctp
├── deploy.sh
├── requirements.txt # 含 vnpy、vnpy_ctp
└── docs/
├── FEATURES.md
├── DEPLOY.md
└── TRADING.md