2026-05-21 05:50:24 +08:00
|
|
|
|
# servers.php 添加服务器优化 — 设计规格
|
|
|
|
|
|
|
2026-05-22 08:19:56 +08:00
|
|
|
|
> ⚠️ **已归档** — 2026-05-22
|
|
|
|
|
|
> 本文档引用的文件结构已过时:`web/servers.php` 已迁移到 `web/app/servers.html` (Tailwind CSS v4 + Alpine.js);`server/services/agent_installer.py` 未独立创建,安装逻辑集成在 server_service.py 中。功能已实现,保留本文档供历史参考。
|
|
|
|
|
|
|
2026-05-21 05:50:24 +08:00
|
|
|
|
**日期**: 2026-05-17
|
|
|
|
|
|
**状态**: 已确认
|
|
|
|
|
|
|
|
|
|
|
|
## 一、需求
|
|
|
|
|
|
|
|
|
|
|
|
1. Agent API 密钥自动生成,不显示在表单
|
|
|
|
|
|
2. 密码预设下拉联动修复
|
|
|
|
|
|
3. 添加服务器后自动 SSH 安装 Agent,实时回传日志
|
|
|
|
|
|
4. 表单新增目标路径字段(必填)
|
|
|
|
|
|
5. 目标路径在列表可快速编辑
|
|
|
|
|
|
|
|
|
|
|
|
## 二、表单改造
|
|
|
|
|
|
|
|
|
|
|
|
### 字段变更
|
|
|
|
|
|
|
|
|
|
|
|
| 字段 | 变更 |
|
|
|
|
|
|
|------|------|
|
|
|
|
|
|
| 名称 | 保持 |
|
|
|
|
|
|
| 域名/IP | 保持,必填 |
|
|
|
|
|
|
| SSH端口 | 保持,默认22 |
|
|
|
|
|
|
| SSH用户名 | 保持,默认root |
|
|
|
|
|
|
| 认证方式 | 保持(密码/密钥) |
|
|
|
|
|
|
| 密码预设 | 保持,修复 datalist 联动 |
|
|
|
|
|
|
| SSH密码 | 必填(需要 SSH 安装 Agent) |
|
|
|
|
|
|
| SSH密钥路径 | 保持(认证方式=密钥时显示) |
|
|
|
|
|
|
| **目标路径** | **新增**,必填,`target_path` |
|
|
|
|
|
|
| Agent端口 | **隐藏**,默认8601 |
|
|
|
|
|
|
| Agent密钥 | **隐藏**,后端自动生成 `bin2hex(random_bytes(16))` |
|
|
|
|
|
|
|
|
|
|
|
|
### 移除字段
|
|
|
|
|
|
|
|
|
|
|
|
- `agent_api_key` 输入框 — 从表单移除
|
|
|
|
|
|
|
|
|
|
|
|
## 三、提交流程
|
|
|
|
|
|
|
|
|
|
|
|
### 3.1 后端 — `POST /api/servers/`
|
|
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
|
def create_server(server_data):
|
|
|
|
|
|
# 1. 自动生成 agent_api_key
|
|
|
|
|
|
server_data.agent_api_key = secrets.token_hex(16) # 32 位 hex
|
|
|
|
|
|
|
|
|
|
|
|
# 2. 创建 server 记录
|
|
|
|
|
|
server = Server(**server_data.model_dump())
|
|
|
|
|
|
db.add(server); db.commit()
|
|
|
|
|
|
|
|
|
|
|
|
# 3. 后台异步安装 Agent
|
|
|
|
|
|
asyncio.create_task(install_agent_async(server.id))
|
|
|
|
|
|
|
|
|
|
|
|
return server
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 3.2 异步安装 — `install_agent_async()`
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
1. 从 DB 读取 server 信息(IP/端口/用户名/密码/目标路径)
|
|
|
|
|
|
2. SSH 连接子服务器
|
|
|
|
|
|
3. 执行命令(通过 Redis pub/sub 逐行回传):
|
2026-05-22 08:19:56 +08:00
|
|
|
|
curl -fsSL https://${NEXUS_DOMAIN}/agent/install.sh | bash -s -- \
|
|
|
|
|
|
--url http://${NEXUS_DOMAIN}:8600 \
|
2026-05-21 05:50:24 +08:00
|
|
|
|
--key <agent_api_key> \
|
|
|
|
|
|
--dirs <target_path>
|
|
|
|
|
|
4. 安装完成 → 更新 server.is_online 状态
|
|
|
|
|
|
5. Redis PUBLISH install:{server_id}:done {"ok": true}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 3.3 进度传输
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
SSH exec_command(install_cmd)
|
|
|
|
|
|
→ stdout.readline() 逐行
|
|
|
|
|
|
→ Redis PUBLISH install:{id}:log {percent: N, line: "..."}
|
|
|
|
|
|
→ WebSocket → 前端渲染
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**Redis key 设计:**
|
|
|
|
|
|
- `install:{server_id}:log` — pub/sub 频道,逐行日志
|
|
|
|
|
|
- `install:{server_id}:state` — JSON `{percent, status: "running|done|failed", error}`
|
|
|
|
|
|
|
|
|
|
|
|
## 四、前端 — 服务器列表
|
|
|
|
|
|
|
|
|
|
|
|
### 4.1 安装进度显示
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
◐ web-02 [安装中 ████████░░ 80%]
|
|
|
|
|
|
↑ 点击弹出日志对话框
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
- `is_online == false && install_state == "running"` → 显示进度条
|
|
|
|
|
|
- 点击进度/状态 → `install_dialog` 弹出,显示实时日志
|
|
|
|
|
|
- 安装完成 → `is_online = true`,进度条消失,显示绿点
|
|
|
|
|
|
- WebSocket 监听 `install:{id}:log`,无需轮询
|
|
|
|
|
|
|
|
|
|
|
|
### 4.2 日志对话框
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
┌─ 安装日志: web-02 ──────────────────┐
|
|
|
|
|
|
│ [1/5] 安装依赖... ✓ │
|
|
|
|
|
|
│ [2/5] 创建目录... ✓ │
|
|
|
|
|
|
│ [3/5] 下载 Agent... ✓ │
|
|
|
|
|
|
│ [4/5] 配置 systemd... ✓ │
|
|
|
|
|
|
│ [5/5] 启动 Agent... ✓ │
|
|
|
|
|
|
│ ✅ 安装完成! │
|
|
|
|
|
|
│ [关闭] │
|
|
|
|
|
|
└──────────────────────────────────────┘
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 4.3 目标路径快速编辑
|
|
|
|
|
|
|
|
|
|
|
|
每行 `target_path` 旁 ✏️ 按钮:
|
|
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
|
点击 ✏️ → target_path 变为 input → 回车 → PUT /api/servers/{id} {target_path: "新路径"}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## 五、涉及文件
|
|
|
|
|
|
|
|
|
|
|
|
| 文件 | 变更 |
|
|
|
|
|
|
|------|------|
|
|
|
|
|
|
| `web/servers.php` | 表单字段调整 + 安装进度 + 快捷编辑 |
|
|
|
|
|
|
| `server/api/servers.py` | create_server 自动生成密钥 + 异步安装入口 |
|
|
|
|
|
|
| `server/services/agent_installer.py` | **新建** — SSH 安装 Agent + Redis 进度推送 |
|
|
|
|
|
|
| `server/main.py` | WebSocket 转发 install:{id}:log → 前端 |
|
|
|
|
|
|
|
|
|
|
|
|
## 六、错误处理
|
|
|
|
|
|
|
|
|
|
|
|
| 场景 | 处理 |
|
|
|
|
|
|
|------|------|
|
|
|
|
|
|
| SSH 连接失败 | `install_state = "failed"`, 显示红色错误,可手动重试 |
|
|
|
|
|
|
| 安装超时(120s) | 超时自动标记失败 |
|
|
|
|
|
|
| 密钥冲突 | 重新生成,重试一次 |
|
|
|
|
|
|
| WebSocket 断开 | 重连后从 Redis 读取当前状态恢复 |
|
|
|
|
|
|
|
|
|
|
|
|
## 七、安装进度状态机
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
pending → running → done
|
|
|
|
|
|
→ failed → (手动重试)→ pending
|
|
|
|
|
|
```
|