Files
memind_adm/docs/DEPLOY.md
T
2026-06-30 20:26:33 +08:00

11 KiB
Raw Blame History

memind_adm 部署与重启

2026-06-26 起,103 / Studio 正式禁止 rsync 发布。
唯一合法入口是 bash scripts/release-prod.sh

本仓库是 本机 Mac 开发仓库。每次开发都必须形成 Git commit;本机不允许直接 rsync103105,只能从本地 commit 打包发布。

管理后台前端(React + Vite)部署到生产 Studio 服务器(SSH 优先 john@10.10.0.2:22,局域网不通时退回 john@58.38.22.103:22)。

环境概览

默认值
部署目标 john@10.10.0.2:/Users/john/Project/memind_admfallback john@58.38.22.103
服务端口 5174
运行方式 vite preview(静态资源 + API 反代)
后端 API 本仓库 server/ADM_API_PORT 默认 8085,与 Memind portal 解耦)
日志 /Users/john/Project/memind_adm/adm-preview.log

硬规则

memind_adm 允许项目独立,不允许用户体系、权限体系、技能体系、策略体系独立

必须遵守:

  1. 用户、登录会话、能力、策略、技能、账单都必须复用 Memind 主实现与主表。
  2. memind_adm 不得再引入或恢复独立后台用户表,例如 auth_usersauth_sessions 这类本地表实现。
  3. admin 账号必须是 Memind 主用户表中的同一账号,npm run admin:init 只允许更新主表账号密码,不允许新建旁路 admin 体系。
  4. 生产环境必须显式指向 Memind 业务模块目录,不能依赖“碰巧命中”的相对路径。
  5. 如果页面出现“用户、能力、技能、策略都是空的”,优先怀疑线上仍在跑旧代码,或 MEMIND_LIB_ROOT / 数据库连接未生效,不要先怀疑前端。

本次事故结论

2026-06-20 这次事故的根因不是生产库没数据,而是 线上 memind_adm 实际仍在跑旧版独立鉴权代码

  1. 旧代码仍在查询 auth_users,没有切到 MemindcreateUserAuth()
  2. 远端 .env 虽然已经指向共享库和主库,但只改环境变量不等于新代码已生效。
  3. scripts/rsync_to_server.sh 默认 不会覆盖远端已有 .env,所以改了本地环境模板后,线上配置不一定会自动更新。

结论:

  1. “页面空”时,先查远端 adm-api.log 有没有 auth_users
  2. 只看“部署脚本成功”不够,必须验远端实际代码和接口返回。
  3. 涉及共享用户体系的改动后,必须做登录和 /admin-api/users 实测。

前置条件

  1. 本机可 SSH 到 Studio 生产机:
    ssh john@10.10.0.2
    
  2. 本机已安装 Node.js,项目依赖已安装(npm install)。
  3. Studio 服务器上 memind_adm Admin API8085 运行(remote_restart.sh 会自动启动),MySQL 与 Memind 共用。
  4. 103 服务器上必须存在可读的 Memind 业务目录,例如 /Users/john/Project/Memind
  5. 远端 .env 必须包含正确的共享环境变量: DATABASE_URLMYSQL_* MEMIND_LIB_ROOT=/Users/john/Project/Memind H5_USERS_ROOT=/Users/john/Project/Memind/users

gadm 独立登录

https://gadm.tkmind.cn 应部署 本仓库 memind_adm,勿再反代到 Memind/ops Vite dev(旧版未登录会跳 localhost:5173)。

说明
登录 本页 /auth/login,账号来自共用 MySQL
会话 设置 H5_PUBLIC_BASE_URL=https://gadm.tkmind.cn不要H5_COOKIE_DOMAIN=.tkmind.cn
路径 https://gadm.tkmind.cn/ 直达超管后台;Plaza 运营在 /ops/ops/admin 已废弃
API ADM_DEV_BACKEND=http://127.0.0.1:8085preview 反代目标)
初始化 admin npm run admin:init 只更新 Memind 主用户表中的 admin 密码,不创建独立后台账号

nginx 示例见 scripts/gadm-nginx.conf.example/ops/ → preview/auth /admin-api /api → Admin API 8085)。

当前规则

  1. 本地当前工作区先打成发布包,不直接覆盖 103。
  2. 发布来源必须是可追溯的本地 commit,不允许从不明工作区直接上线。
  3. 103 在切换前必须做 memind_adm 全量备份。
  4. 发布包不能带 .env、日志、pid 文件、.mindops/ 等运行态资产。
  5. 103 必须先在 release 目录完成解包、npm installnpm run build,再切换 live 目录。
  6. 切换后必须通过 Admin API 和前台首页健康检查;失败立即回滚。

唯一入口

bash scripts/release-prod.sh --dry-run
bash scripts/release-prod.sh

产物发布流程

  1. 本地生成 memind-adm-<release-id>.tar.gz 和发布清单。
  2. 通过 scp 上传到 103 的 incoming/memind_adm/
  3. 103 备份当前 /Users/john/Project/memind_adm 为时间戳压缩包。
  4. /Users/john/Project/releases/ 下解包新版本。
  5. 从当前 live 目录继承运行态配置与日志文件。
  6. 在 release 目录安装依赖、构建。
  7. 原子切换 memind_adm live 目录。
  8. 调用 scripts/remote_restart.sh 重启 80855174
  9. 检查 127.0.0.1:8085/health127.0.0.1:5174/

禁止事项

  • 禁止 scripts/rsync_to_server.sh
  • 禁止手工拖文件覆盖 103
  • 禁止在 103 直接改源码后继续跑
  • 禁止跳过备份和健康检查

更新部署(历史)

下方 rsync 流程只保留作事故回溯背景。生产发布不要再照做。

旧流程示例:

./scripts/rsync_to_server.sh

脚本会依次:

  1. 本地 npm run build 生成 dist/
  2. rsync 同步源码到远端(排除 node_modules.git.env 等)
  3. 单独同步 dist/
  4. 若远端尚无 .env,写入默认配置(不覆盖已有 .env
  5. 调用 scripts/remote_restart.sh 重启服务

注意:

  1. 如果本次改动涉及 DATABASE_URLMYSQL_*MEMIND_LIB_ROOTH5_USERS_ROOT,需要手动同步远端 .envrsync_to_server.sh 不会覆盖已有远端 .env
  2. 如果本次改动涉及共享用户体系,部署完成后必须执行下文“共享用户体系验收”。
  3. 如果希望“套餐管理”自动同步到生产后台,还需要在远端 .env 配置 PLAN_SYNC_TARGET_BASE_URLPLAN_SYNC_USERNAMEPLAN_SYNC_PASSWORD

常用参数(历史)

# 跳过本地构建(沿用当前 dist/)
./scripts/rsync_to_server.sh --skip-build

# 只同步文件,不重启
./scripts/rsync_to_server.sh --no-restart

# 环境变量覆盖
DEPLOY_HOST=john@10.10.0.2 \
REMOTE_DIR=/Users/john/Project/memind_adm \
ADM_PORT=5174 \
./scripts/rsync_to_server.sh

仅重启服务

代码已在远端、无需重新同步时:

ssh john@10.10.0.2 'ADM_ROOT=/Users/john/Project/memind_adm ADM_PORT=5174 bash -s' \
  < scripts/remote_restart.sh

或在 100 服务器上直接执行:

cd /Users/john/Project/memind_adm
ADM_PORT=5174 ./scripts/remote_restart.sh

重启逻辑:结束占用 5174 的进程 → nohup npm run preview → 检查首页是否返回 200。

验证

本机通过 SSH 检查:

ssh john@10.10.0.2 'curl -sI http://127.0.0.1:5174/ | head -1'
# 期望: HTTP/1.1 200 OK

查看远端日志:

ssh john@10.10.0.2 'tail -f /Users/john/Project/memind_adm/adm-preview.log'

远端配置

编辑远端 .env(首次部署后路径:/Users/john/Project/memind_adm/.env):

# preview 反代目标(/auth、/admin-api、/api)— 指向本仓库 Admin API
ADM_API_PORT=8085
ADM_DEV_BACKEND=http://127.0.0.1:8085
H5_PUBLIC_BASE_URL=https://gadm.tkmind.cn
VITE_BASE_PATH=/ops

# 共享 Memind 主库与主实现
DATABASE_URL=mysql://<user>:<password>@<host>:3306/<db>
MEMIND_LIB_ROOT=/Users/john/Project/Memind
H5_USERS_ROOT=/Users/john/Project/Memind/users

# 套餐自动同步到生产后台(可选)
PLAN_SYNC_TARGET_BASE_URL=https://gadm.tkmind.cn
PLAN_SYNC_USERNAME=admin
PLAN_SYNC_PASSWORD=<admin-password>
PLAN_SYNC_TIMEOUT_MS=10000

# 「返回对话」跳转主 H5(可选)
VITE_MAIN_APP_URL=https://h5.tkmind.cn

修改 .env 后需重启服务生效。

共享用户体系验收

每次涉及用户/权限/技能/策略相关改动后,部署完成必须至少执行一次:

  1. 看远端代码是否已切到共享实现:
    ssh john@10.10.0.2 'cd /Users/john/Project/memind_adm && sed -n "1,80p" server/bootstrap.mjs'
    
    期望:出现 createUserAuth,而不是 createLocalUserAuth
  2. 看远端 server/local-auth.mjs 是否只剩 cookie 工具:
    ssh john@10.10.0.2 'cd /Users/john/Project/memind_adm && sed -n "1,80p" server/local-auth.mjs'
    
    期望:没有 auth_usersauth_sessionscreateLocalUserAuth
  3. 看启动日志是否仍出现旧表查询:
    ssh john@10.10.0.2 'cd /Users/john/Project/memind_adm && tail -n 120 adm-api.log'
    
    期望:没有 auth_users;出现 Admin DB connectedMemind lib: /Users/john/Project/Memind
  4. 实测登录和用户接口:
    ssh john@10.10.0.2 'python3 - <<\"PY\"
    

import requests s = requests.Session() base = "http://127.0.0.1:8085" print(s.post(base + "/auth/login", json={"username":"admin","password":""}).status_code) resp = s.get(base + "/admin-api/users", params={"page": 1, "pageSize": 5}) print(resp.status_code) print(resp.text[:800]) PY'

期望:`/admin-api/users` 返回 200,且结果中能看到共享主表用户数据,不是空列表。

## 故障排查

| 现象 | 处理 |
|---|---|
| `无法 SSH 到 john@10.10.0.2` | 先确认局域网可达;不通时改走 `john@58.38.22.103`,必要时再执行 `ssh-copy-id john@58.38.22.103` |
| 首页 200 但登录失败 | 检查 Studio 上 `8085` Admin API 是否运行(`curl http://127.0.0.1:8085/health` |
| 用户、能力、技能、策略全空 | 先查 `adm-api.log` 是否仍有 `auth_users`;再核对远端 `server/bootstrap.mjs` 是否已切到 `createUserAuth()`;再核对远端 `.env` 的 `MEMIND_LIB_ROOT` 与 `DATABASE_URL` |
| 打开后跳 localhost:5173 | nginx 仍指向 Memind/ops dev;改反代到 memind_adm `:5174`,并重新部署 |
| `dist 不存在` | 先在本机 `npm run build`,或完整执行 `./scripts/rsync_to_server.sh` |
| 启动失败 | 查看 `adm-preview.log`;确认远端 Node 在 PATH 中(需 Homebrew `node@22` 等) |
| 端口被占用 | `remote_restart.sh` 会自动 kill 旧进程;仍异常时可手动 `lsof -iTCP:5174 -sTCP:LISTEN` |

## 相关脚本

| 脚本 | 说明 |
|---|---|
| `scripts/release-prod.sh` | 本地打发布包并推送到 103,再由 103 备份、解包、切换、重启 |
| `scripts/rsync_to_server.sh` | 已禁用,仅保留禁用提示 |
| `scripts/remote_restart.sh` | 仅在远端重启 `vite preview` |
| `scripts/.releaseignore-prod` | 生产发布包排除规则 |

## 规则文档

- `ENGINEERING_WORKFLOW_RULES.md`
- `DEVELOPMENT_RELEASE_RULES.md`
- `TEST_RELEASE_RULES.md`
- `PRODUCTION_RELEASE_RULES.md`