# gate_scout_order · 手动备份与恢复 面向 **Ubuntu 服务器**,项目固定在 `/opt/gate_scout_order`,备份目录在 `/root`。 `config.yaml` 与 `runtime/` **不入 Git**。升级、`git pull`、误删目录前,请先执行下方 **一键备份**。 --- ## 路径约定 | 用途 | 路径 | |------|------| | 项目根目录 | `/opt/gate_scout_order` | | 扫描端 | `/opt/gate_scout_order/onchain_scout_gate` | | 执行器 | `/opt/gate_scout_order/gate_order_executor` | | 备份根目录 | `/root/backup_gate_<日期>_<时间>/` | PM2 默认进程名:`onchain-scout`、`gate-order-executor`(若你改过名,恢复命令里请自行替换)。 --- ## 备份内容说明 ### 必须备份(丢失难恢复) | 组件 | 文件 | 说明 | |------|------|------| | 扫描端 | `config.yaml` | 企微、auth、proxy、monitor 等 | | 扫描端 | `runtime/alerts.db` | 历史告警、面板策略参数(SQLite KV) | | 扫描端 | `runtime/order_executors.json` | 执行器转发列表、总开关、Webhook 密钥 | | 执行器 | `config.yaml` | Gate API、`webhook_secret`、`dry_run` 等 | | 执行器 | `runtime/signals.sqlite` | 信号流与每笔下单结果 | | 执行器 | `runtime/risk_prefs.json` | 面板「最低盈亏比」 | | 执行器 | `runtime/breakeven_prefs.json` | 移动保本开关 | | 执行器 | `runtime/breakeven_active.json` | 移动保本运行态 | ### 可选(排障用,体积较大) 扫描端 / 执行器 `runtime/*.log`、`runtime/pm2-*.log` — 下方一键脚本 **默认不备份日志**;需要时见 [§5 可选:含日志备份](#5-可选含日志备份)。 ### 多执行器 若除 `gate_order_executor` 外还有 **第二套执行器**(另一目录或 `:8091` 实例),请对该目录 **再执行一次** 备份块,或把路径改后单独打包(见 [§6 多执行器](#6-多执行器))。 --- ## 1. 一键备份(推荐) 在服务器上 **整段复制执行**(需已安装 `sqlite3`:`sudo apt install -y sqlite3`)。 ```bash PROJECT_ROOT=/opt/gate_scout_order BACKUP_DIR=/root/backup_gate_$(date +%Y%m%d_%H%M%S) SCOUT="$PROJECT_ROOT/onchain_scout_gate" EXEC="$PROJECT_ROOT/gate_order_executor" mkdir -p "$BACKUP_DIR"/{onchain_scout_gate/runtime,gate_order_executor/runtime} chmod 700 "$BACKUP_DIR" # --- 扫描端 config --- if [ -f "$SCOUT/config.yaml" ]; then cp -a "$SCOUT/config.yaml" "$BACKUP_DIR/onchain_scout_gate/" else echo "WARN: 缺少 $SCOUT/config.yaml" fi # --- 扫描端 runtime(SQLite 用 .backup,其余 cp)--- if [ -f "$SCOUT/runtime/alerts.db" ]; then sqlite3 "$SCOUT/runtime/alerts.db" ".backup '$BACKUP_DIR/onchain_scout_gate/runtime/alerts.db'" else echo "WARN: 缺少 alerts.db" fi [ -f "$SCOUT/runtime/order_executors.json" ] && \ cp -a "$SCOUT/runtime/order_executors.json" "$BACKUP_DIR/onchain_scout_gate/runtime/" # --- 执行器 config --- if [ -f "$EXEC/config.yaml" ]; then cp -a "$EXEC/config.yaml" "$BACKUP_DIR/gate_order_executor/" else echo "WARN: 缺少 $EXEC/config.yaml" fi # --- 执行器 runtime --- if [ -f "$EXEC/runtime/signals.sqlite" ]; then sqlite3 "$EXEC/runtime/signals.sqlite" ".backup '$BACKUP_DIR/gate_order_executor/runtime/signals.sqlite'" else echo "WARN: 缺少 signals.sqlite" fi for f in risk_prefs.json breakeven_prefs.json breakeven_active.json; do [ -f "$EXEC/runtime/$f" ] && cp -a "$EXEC/runtime/$f" "$BACKUP_DIR/gate_order_executor/runtime/" done echo "备份完成: $BACKUP_DIR" find "$BACKUP_DIR" -type f | sort ls -la "$BACKUP_DIR"/onchain_scout_gate "$BACKUP_DIR"/gate_order_executor 2>/dev/null || true ``` 执行成功后记下输出的目录名,例如:`/root/backup_gate_20260517_033012`。 --- ## 2. 查看已有备份 ```bash ls -lt /root/backup_gate_* 2>/dev/null | head -20 ``` 查看最新一份目录路径: ```bash ls -dt /root/backup_gate_* 2>/dev/null | head -1 ``` --- ## 3. 一键恢复 **恢复会覆盖当前 `config.yaml` 与列出的 runtime 文件。** 建议先做一次 [§1 一键备份](#1-一键备份推荐),再执行恢复。 将 `BACKUP_DIR` 改成你要恢复的那次备份路径(整段复制后只改第一行): ```bash BACKUP_DIR=/root/backup_gate_20260517_033012 PROJECT_ROOT=/opt/gate_scout_order SCOUT="$PROJECT_ROOT/onchain_scout_gate" EXEC="$PROJECT_ROOT/gate_order_executor" if [ ! -d "$BACKUP_DIR" ]; then echo "ERROR: 备份目录不存在: $BACKUP_DIR" exit 1 fi pm2 stop onchain-scout gate-order-executor 2>/dev/null || true mkdir -p "$SCOUT/runtime" "$EXEC/runtime" # 扫描端 [ -f "$BACKUP_DIR/onchain_scout_gate/config.yaml" ] && \ cp -a "$BACKUP_DIR/onchain_scout_gate/config.yaml" "$SCOUT/" [ -f "$BACKUP_DIR/onchain_scout_gate/runtime/alerts.db" ] && \ cp -a "$BACKUP_DIR/onchain_scout_gate/runtime/alerts.db" "$SCOUT/runtime/" [ -f "$BACKUP_DIR/onchain_scout_gate/runtime/order_executors.json" ] && \ cp -a "$BACKUP_DIR/onchain_scout_gate/runtime/order_executors.json" "$SCOUT/runtime/" # 执行器 [ -f "$BACKUP_DIR/gate_order_executor/config.yaml" ] && \ cp -a "$BACKUP_DIR/gate_order_executor/config.yaml" "$EXEC/" [ -f "$BACKUP_DIR/gate_order_executor/runtime/signals.sqlite" ] && \ cp -a "$BACKUP_DIR/gate_order_executor/runtime/signals.sqlite" "$EXEC/runtime/" for f in risk_prefs.json breakeven_prefs.json breakeven_active.json; do [ -f "$BACKUP_DIR/gate_order_executor/runtime/$f" ] && \ cp -a "$BACKUP_DIR/gate_order_executor/runtime/$f" "$EXEC/runtime/" done pm2 restart onchain-scout gate-order-executor 2>/dev/null || \ (cd "$SCOUT" && pm2 start deploy/ecosystem.config.cjs; cd "$EXEC" && bash deploy/pm2-start.sh) pm2 save 2>/dev/null || true echo "恢复完成,自 $BACKUP_DIR" pm2 status ``` 恢复后检查: - 扫描端面板 `http://<服务器>:8088` — 策略参数、执行器列表是否正常 - 执行器面板 `http://<服务器>:8090/dashboard` — 信号流历史是否仍在 **注意:** `git pull` 后不要用 `git checkout -- runtime/` 或 `git clean` 清掉业务数据。 --- ## 4. 从「最新一份备份」恢复(可选) 若你确认 `/root` 下最新目录就是要用的那份,可先取路径再恢复: ```bash BACKUP_DIR=$(ls -dt /root/backup_gate_* 2>/dev/null | head -1) echo "将恢复: $BACKUP_DIR" read -r -p "确认请输入 yes: " ans [ "$ans" = "yes" ] || { echo "已取消"; exit 1; } PROJECT_ROOT=/opt/gate_scout_order SCOUT="$PROJECT_ROOT/onchain_scout_gate" EXEC="$PROJECT_ROOT/gate_order_executor" pm2 stop onchain-scout gate-order-executor 2>/dev/null || true mkdir -p "$SCOUT/runtime" "$EXEC/runtime" cp -a "$BACKUP_DIR/onchain_scout_gate/config.yaml" "$SCOUT/" 2>/dev/null || true cp -a "$BACKUP_DIR/onchain_scout_gate/runtime/"* "$SCOUT/runtime/" 2>/dev/null || true cp -a "$BACKUP_DIR/gate_order_executor/config.yaml" "$EXEC/" 2>/dev/null || true cp -a "$BACKUP_DIR/gate_order_executor/runtime/"* "$EXEC/runtime/" 2>/dev/null || true pm2 restart onchain-scout gate-order-executor 2>/dev/null || true pm2 save 2>/dev/null || true echo "已从 $BACKUP_DIR 恢复" ``` --- ## 5. 可选:含日志备份 需要连同日志一起打包时,在 **§1 备份脚本末尾** 追加执行: ```bash PROJECT_ROOT=/opt/gate_scout_order BACKUP_DIR=/root/backup_gate_$(date +%Y%m%d_%H%M%S)_with_logs SCOUT="$PROJECT_ROOT/onchain_scout_gate" EXEC="$PROJECT_ROOT/gate_order_executor" mkdir -p "$BACKUP_DIR" chmod 700 "$BACKUP_DIR" cp -a "$SCOUT/config.yaml" "$BACKUP_DIR/scout_config.yaml" 2>/dev/null || true cp -a "$EXEC/config.yaml" "$BACKUP_DIR/executor_config.yaml" 2>/dev/null || true cp -a "$SCOUT/runtime" "$BACKUP_DIR/onchain_scout_gate_runtime" cp -a "$EXEC/runtime" "$BACKUP_DIR/gate_order_executor_runtime" echo "含日志备份完成: $BACKUP_DIR" du -sh "$BACKUP_DIR" ``` 含日志的目录结构与 §1 不同,恢复时请手动 `cp` 对应子目录,或优先使用 §1 标准结构备份。 --- ## 6. 多执行器 第二套执行器若在例如 `/opt/gate_scout_order/gate_order_executor_b`: ```bash EXTRA_EXEC=/opt/gate_scout_order/gate_order_executor_b BACKUP_DIR=/root/backup_gate_$(date +%Y%m%d_%H%M%S)_exec_b mkdir -p "$BACKUP_DIR/runtime" chmod 700 "$BACKUP_DIR" cp -a "$EXTRA_EXEC/config.yaml" "$BACKUP_DIR/" [ -f "$EXTRA_EXEC/runtime/signals.sqlite" ] && \ sqlite3 "$EXTRA_EXEC/runtime/signals.sqlite" ".backup '$BACKUP_DIR/runtime/signals.sqlite'" for f in risk_prefs.json breakeven_prefs.json breakeven_active.json; do [ -f "$EXTRA_EXEC/runtime/$f" ] && cp -a "$EXTRA_EXEC/runtime/$f" "$BACKUP_DIR/runtime/" done echo "第二执行器备份: $BACKUP_DIR" ``` --- ## 7. 建议操作时机 | 场景 | 建议 | |------|------| | 首次部署稳定运行后 | 立刻备份一份 | | `git pull` / 改目录 / 重装系统前 | 先备份 | | 改 `config.yaml` 或面板大批量改策略前 | 先备份 | | 定期(手动) | 每周或每月一次,保留多份不同日期的目录 | 可将备份目录同步到另一台机器或对象存储(scp、rsync 等),**不要**把含 API 密钥的备份放到公开网盘。 --- ## 8. 故障速查 | 现象 | 可能原因 | |------|----------| | 升级后面板策略丢了 | 未恢复 `runtime/alerts.db` | | 执行器列表空了 | 未恢复 `order_executors.json` | | 信号流历史没了 | 未恢复 `signals.sqlite` | | `sqlite3: command not found` | 执行 `sudo apt install -y sqlite3` 后重跑备份 | | 恢复后 PM2 起不来 | `pm2 logs` 看配置校验;检查端口占用 | 更多部署与升级说明见 [部署说明.md](部署说明.md)。