Guanghu Domestic Migration a27e87cb99 chore: import sanitized domestic snapshot for REPO-007
Source snapshot: 97d7f0fae96dc04b7ddad56fc1db6a108ed662cc

[SEC-CLEAN] · pre-push-clean v1.0 · 109处敏感信息已自动转乱码
2026-07-17 15:59:55 +08:00

206 lines
5.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# GHCS v0.2 终端排障 SOPSSH Web Terminal Debug SOP
<aside>
🎯
本页用途:当 GHCS v0.2 的 SSH Web 终端出现「页面能开但连不上 / 能连但不能输入 / 焦点丢失 / 反复修不好」时,按固定流程快速定位。
原则:**先排通路,再看交互**先用可观测证据HTTP 状态码 / 命令回显),不要凭“光标看起来在不在”。
</aside>
---
## 1本次问题的具体原因复盘结论
### 1.1 真正卡住不是一个 bug而是三层叠加
1) **页面 200 ≠ 终端可用**
- `/console/terminal` 返回 200 只说明 Next 页面渲染成功。
- 终端真正依赖:`GET /ws/terminal/servers` + `WS /ws/terminal/{server_key}`
- 只要后端路由未挂载、或前端没打到正确后端,页面仍 200但终端必失败。
2) **环境变量未生效 / [localhost](http://localhost) 解析导致“像玄学”**
- `NEXT_PUBLIC_CONSOLE_API` 改了但未重启前端 → Next 继续用旧值。
- `localhost` 在部分环境可能走 IPv6`::1`)而后端仅在 IPv4`127.0.0.1`)监听 → 表现为偶发连不上 / 重试。
3) **焦点判断误区:光标渲染 ≠ 键盘输入通道**
- xterm 光标是渲染状态,点别处后仍可能停在原位。
- 真正需要判断的是:键盘输入是否进入终端(用 `echo` 回显验证)。
### 1.2 之前陷入的误区(导致一直修不动)
- **误区 A把“页面能打开”当成“后端都通了”**
- **误区 B用光标/感觉判断焦点**,而不是用命令回显判定输入通道
- **误区 C`.env.local` 不重启前端**,导致“我明明改了但没变化”
- **误区 D一次改太多前端/后端/依赖/配置一起动)**,失去最小证据链
### 1.3 本次为什么修得顺利(方法)
把问题拆成 4 层,并且每层只用一个“最小证据”验收:
- 后端活着:`/docs` 能开
- 路由挂载:`curl -i /ws/terminal/servers` 看 200/404
- 前端指向正确后端:`.env.local` + 重启
- 交互与焦点:`whoami / pwd / echo ...` 回显
---
## 2GHCS v0.2 终端排障 SOP五段式不跳步
### Step 0准备两窗口
- 终端 AbackendFastAPI
- 终端 BfrontendNext.js
---
### Step 1确认后端在跑
```bash
cd ~/guanghu-dev/ghcs-mono/backend
source venv/bin/activate
python -m uvicorn main:app --host 127.0.0.1 --port 5002 --reload
```
验收:浏览器打开 `http://127.0.0.1:5002/docs`
---
### Step 2确认 terminal_router 已挂载(最关键一锤)
```bash
curl -i http://127.0.0.1:5002/ws/terminal/servers
```
- **200 + JSON**:后端终端路由 OK
- **404**:检查 `backend/main.py` 是否包含:
- `from terminal_router import router as terminal_router`
- `app.include_router(terminal_router)`
---
### Step 3确认前端 API_BASE 指向正确,并且已重启生效
```bash
cd ~/guanghu-dev/ghcs-mono/frontend
cat -n .env.local
```
推荐:
```
NEXT_PUBLIC_CONSOLE_API=http://127.0.0.1:5002
```
**改完必须重启前端**
```bash
npm run dev
```
---
### Step 4确认“页面可用”与“后端可达”不是一回事
打开:`http://localhost:3000/console/terminal`
验收点:服务器下拉是否能显示(来自 Step 2 的 servers 列表)。
---
### Step 5交互与焦点验收只看回显不看光标
连接成功后输入:
```bash
whoami
pwd
echo FOCUS_OK
```
期望回显:用户名、路径、`FOCUS_OK`
#### 5.1 点击聚焦验收(对应历史 bug
1) 点页面别处
2) 点回黑框
3) 输入:
```bash
echo CLICK_FOCUS_OK
```
期望回显 `CLICK_FOCUS_OK`
#### 5.2 额外:判断是否一直保持输入通道
点页面别处后,**不点回终端**,直接键盘敲:
```bash
echo SHOULD_APPEAR
```
- 若回显:说明输入通道仍在
- 若不回显:说明焦点确实丢失,需要启用“保险带补丁”
---
## 3常见故障 → 快速定位表
- **页面能开,但服务器下拉空**:优先回到 Step 2/3路由未挂载或 API_BASE 未生效)
- **连接按钮报 WS error**:先跑 `curl -i /ws/terminal/servers` 判 200/404再看浏览器 Network → WS
- **能连但不能输入**:先用 `echo` 判输入通道是否断,再考虑焦点补丁
- **输入重复**:检查是否每次 connect 都重复绑定 xterm 的 `onData`(应只绑定一次或重连前清理)
---
## 3.5|关键数据备忘(防遗忘)
### 3.5.1 本地端口与环境变量
- 后端console-api`http://127.0.0.1:5002`
- 前端Next dev`http://localhost:3000`
- 前端环境变量文件:`~/guanghu-dev/ghcs-mono/frontend/.env.local`
- `NEXT_PUBLIC_CONSOLE_API=http://127.0.0.1:5002`
- ⊢ 改 `.env.local` 后必须重启 `npm run dev` 才会生效
### 3.5.2 登录与 Bearer tokenAPI Keys 写操作必用)
- 登录接口:`POST /api/login`
- 返回字段:`access_token` + `token_type: bearer`
- 本地默认管理员账号(见 `backend/auth.py``awen / guanghu2026`
- 前端 token 存储位置(本次约定):`localStorage.ghcs_access_token`
- 写请求必须带 header`Authorization: Bearer <access_token>`
### 3.5.3 API Keys 关键接口(本次已验收)
- `GET /api/keys/suppliers`(当前可不鉴权)
- `GET /api/keys/list`(当前可不鉴权)
- `POST /api/keys/add`(需鉴权)
- `PUT /api/keys/{id}`(需鉴权;启停开关)
- `DELETE /api/keys/{id}`(需鉴权)
---
## 4推荐的“保险带补丁”可选但建议保留
若遇到“点回黑框无法找回输入”,给终端容器外层加:
```tsx
onMouseUp={() => term.current?.focus()}
```
这能把“点黑框回焦”变成确定性行为。
---
## 5本次会话验收回执可复制到执行记录
- `curl -i http://127.0.0.1:5002/ws/terminal/servers` → 200
- 终端回显:`whoami` / `pwd` / `echo FOCUS_OK` / `echo CLICK_FOCUS_OK` / `echo SHOULD_APPEAR` 全通过