docs: 设计deploy Linux远程运维方案

This commit is contained in:
2026-05-21 16:44:42 +08:00
parent 9a9614a9e5
commit ba8bc43377

View File

@@ -0,0 +1,514 @@
# Linux 服务器部署运维设计
## 1. 背景
`system-ops/deploy` 当前只提供系统部署菜单的基础入口:
- `GET /deploy/overview`
- `DeployController`
- `DeployService`
- `DeployOverviewVO`
本次需求是在 `deploy` 模块中补充 Linux 服务器远程运维能力。用户可以维护 Linux 服务器连接配置,基于 SSH/SFTP 连接服务器,完成远程文件上传、下载和基础命令终端操作。命令终端目标体验接近 Xshell 的基础能力。
当前仓库没有前端代码,本设计只定义页面布局、接口契约、后端模块拆分、数据存储和验证方式,不实现真实前端页面。
## 2. 范围确认
本期只支持 Linux 服务器。
本期包含:
- Linux SSH 连接配置的新增、编辑、删除、查询。
- SSH 连接测试。
- SFTP 文件列表、上传、下载、删除、新建目录。
- SSH Shell 基础命令交互。
- 前端单页运维工作台布局设计。
- 连接配置使用文件方式存储,不新建数据库表。
本期不包含:
- Windows 服务器。
- FTP 协议。
- 数据库存储连接配置。
- 部署任务编排。
- 命令审批、命令黑名单、命令历史。
- 批量文件压缩下载。
- 数据库专用客户端封装。
- Maven 编译、打包、测试。
说明:需求中提到的 “FPT” 本期按 Linux 服务器常用能力理解为 SFTP。SFTP 复用 SSH 账号、密码和端口,比单独 FTP 更适合本期场景。
## 3. 总体方案
推荐采用 “SSH/SFTP + WebSocket 终端” 方案:
- 服务器连接配置保存到本地 JSON 文件。
- 后端通过 SSH 建立 Linux 连接。
- 文件操作通过 SFTP 通道完成。
- 终端操作通过 SSH Shell 通道完成。
- 前端通过 WebSocket 与后端交换终端输入输出。
该方案可以复用同一份服务器连接配置,不需要引入 Windows 远程协议,也能满足类 Xshell 的基础交互需求。
## 4. 前端页面布局
页面路径建议沿用当前菜单路径:
```text
/systemOps/deploy
```
页面采用三块工作区:
- 左侧:服务器列表。
- 中间:远程文件管理。
- 右侧:连接详情和快捷操作。
- 底部SSH 终端区。
推荐布局:
```text
┌──────────────────────────────────────────────────────────────┐
│ 顶部工具栏:新增连接 测试连接 刷新 当前连接状态 │
├──────────────┬──────────────────────────────┬────────────────┤
│ 服务器列表 │ 远程文件管理 │ 连接详情/操作 │
│ │ │ │
│ Linux-测试 │ 路径栏:/opt/app │ 主机/IP │
│ Linux-生产 │ 上传 下载 新建目录 删除 刷新 │ 用户名 │
│ │ │ 端口 │
│ │ 文件表格 │ 测试连接 │
│ │ │ 打开终端 │
├──────────────┴──────────────────────────────┴────────────────┤
│ 终端 TabsLinux-测试 │
│ $ pwd │
│ /opt/app │
└──────────────────────────────────────────────────────────────┘
```
### 4.1 服务器列表
左侧服务器列表用于选择当前操作目标。
展示字段:
| 字段 | 说明 |
|---|---|
| 名称 | 服务器显示名称 |
| 主机地址 | IP 或域名 |
| SSH 端口 | 默认 22 |
| 连接状态 | 未测试、连接成功、连接失败 |
交互:
- 支持按名称、主机地址搜索。
- 点击服务器后加载连接详情,并将文件管理区切换到该服务器。
- 列表项提供编辑、删除、测试连接入口。
- 删除连接前必须二次确认。
### 4.2 连接配置弹窗
新增和编辑使用同一个弹窗。
字段:
| 字段 | 是否必填 | 说明 |
|---|---|---|
| 名称 | 是 | 页面展示名称 |
| 主机地址 | 是 | Linux 服务器 IP 或域名 |
| SSH 端口 | 是 | 默认 22范围 1-65535 |
| 用户名 | 是 | SSH 登录用户 |
| 密码 | 新增必填 | 编辑时留空表示不修改 |
| 备注 | 否 | 环境说明 |
按钮:
- 测试连接。
- 保存。
- 取消。
密码规则:
- 新增连接时密码必填。
- 编辑连接时密码不回显。
- 编辑时密码为空表示沿用原密码。
- 查询列表和详情接口均不返回密码。
### 4.3 远程文件管理
中间文件管理区基于当前选中的服务器工作。
顶部路径栏:
- 展示当前远程目录,例如 `/opt/app`
- 支持返回上级目录。
- 支持点击面包屑跳转到上级路径。
工具栏:
- 上传。
- 下载。
- 新建目录。
- 删除。
- 刷新。
文件表格字段:
| 字段 | 说明 |
|---|---|
| 名称 | 文件或目录名称 |
| 类型 | 文件、目录、软链接 |
| 大小 | 文件大小,目录可为空 |
| 权限 | Linux 权限字符串 |
| 修改时间 | 远程文件修改时间 |
交互规则:
- 双击目录进入下级目录。
- 下载只支持普通文件。
- 删除文件或目录前必须二次确认。
- 本期支持单文件上传和单文件下载。
- 上传目标目录为当前路径。
- 下载目录、批量压缩下载不在本期范围。
### 4.4 SSH 终端区
底部终端区用于执行 Linux 命令。
交互规则:
- 点击“打开终端”后创建 SSH Shell 会话。
- 前端输入通过 WebSocket 实时发送给后端。
- 后端将 Shell 输出通过 WebSocket 实时推送给前端。
- 本期建议限制为每台服务器最多一个终端会话。
- 关闭终端 Tab 时通知后端释放 SSH 会话。
- 终端断开后显示状态,不自动重连。
用户可以在终端中自行执行数据库命令,例如:
```bash
mysql -uroot -p
psql -h 127.0.0.1 -U postgres
redis-cli
```
后端不解析数据库命令,也不保存命令历史。
## 5. 后端结构设计
`system-ops/deploy` 模块内按职责新增类,保留现有 `DeployController``/deploy/overview`
建议结构:
```text
system-ops/deploy/src/main/java/com/njcn/gather/systemops/deploy/
├── config/
├── controller/
├── pojo/param/
├── pojo/vo/
├── pojo/dto/
├── repository/
├── service/
├── service/impl/
└── websocket/
```
职责拆分:
| 类 | 职责 |
|---|---|
| `DeployServerController` | 连接配置查询、新增、编辑、删除、测试连接 |
| `DeployFileController` | SFTP 文件列表、上传、下载、删除、新建目录 |
| `DeployTerminalWebSocketHandler` | SSH 终端 WebSocket 输入输出转发 |
| `DeployServerConfigService` | 连接配置业务校验和编排 |
| `DeployServerConfigRepository` | JSON 文件读写 |
| `DeploySftpService` | SFTP 文件操作 |
| `DeploySshTerminalService` | SSH Shell 会话创建、输入、输出、关闭 |
| `DeployCryptoService` | 密码加密和解密 |
| `DeployProperties` | deploy 配置项绑定 |
## 6. 连接配置存储
连接配置不入库,使用 JSON 文件落盘。存储目录通过配置指定。
建议配置:
```yaml
deploy:
storage-dir: ${log.homeDir}/deploy
terminal-idle-timeout-minutes: 30
```
`deploy.crypto-key` 不建议在默认 `application.yml` 中配置明文值。后续实现时可通过环境覆盖或外部配置提供,业务代码只读取配置,不写死密钥。
落盘文件:
```text
D:\logs\deploy\deploy-server-connections.json
```
JSON 结构:
```json
{
"servers": [
{
"id": "uuid",
"name": "测试服务器",
"host": "192.168.1.10",
"sshPort": 22,
"username": "root",
"password": "加密密文",
"description": "测试环境",
"createdTime": "2026-05-21 14:00:00",
"updatedTime": "2026-05-21 14:00:00"
}
]
}
```
写文件规则:
- 启动时如果文件不存在,自动创建空配置文件。
- 读写方法集中在 `DeployServerConfigRepository`
- 写入时先写临时文件,再替换正式文件,避免进程中断导致 JSON 损坏。
- 保存和删除操作需要加进程内锁,避免并发写入互相覆盖。
密码规则:
- 密码必须加密后落盘。
- 接口返回不包含密码。
- 日志不打印密码。
- 优先复用项目已有加密能力;如没有合适工具,则在 `deploy` 内封装 AES 加解密组件。
- 加密密钥通过配置提供,不在业务代码中硬编码。
## 7. 接口设计
接口风格沿用当前仓库常见写法:查询和变更优先使用 `POST`,返回 `HttpResult<T>`
### 7.1 连接配置接口
| 方法 | 路径 | 说明 |
|---|---|---|
| `POST` | `/deploy/server/list` | 查询服务器连接配置列表 |
| `POST` | `/deploy/server/add` | 新增服务器连接配置 |
| `POST` | `/deploy/server/update` | 修改服务器连接配置 |
| `POST` | `/deploy/server/delete` | 删除服务器连接配置 |
| `POST` | `/deploy/server/test` | 测试 SSH 连接 |
列表返回字段:
| 字段 | 说明 |
|---|---|
| `id` | 连接 ID |
| `name` | 服务器名称 |
| `host` | 主机地址 |
| `sshPort` | SSH 端口 |
| `username` | 用户名 |
| `description` | 备注 |
| `createdTime` | 创建时间 |
| `updatedTime` | 更新时间 |
新增参数:
| 字段 | 是否必填 |
|---|---|
| `name` | 是 |
| `host` | 是 |
| `sshPort` | 是 |
| `username` | 是 |
| `password` | 是 |
| `description` | 否 |
编辑参数:
| 字段 | 是否必填 | 说明 |
|---|---|---|
| `id` | 是 | 连接 ID |
| `name` | 是 | 服务器名称 |
| `host` | 是 | 主机地址 |
| `sshPort` | 是 | SSH 端口 |
| `username` | 是 | 用户名 |
| `password` | 否 | 为空表示不修改 |
| `description` | 否 | 备注 |
### 7.2 文件接口
| 方法 | 路径 | 说明 |
|---|---|---|
| `POST` | `/deploy/file/list` | 查询远程目录文件列表 |
| `POST` | `/deploy/file/mkdir` | 新建远程目录 |
| `POST` | `/deploy/file/delete` | 删除远程文件或目录 |
| `POST` | `/deploy/file/upload` | 上传本地文件到远程目录 |
| `POST` | `/deploy/file/download` | 下载远程普通文件 |
文件列表参数:
| 字段 | 是否必填 | 说明 |
|---|---|---|
| `serverId` | 是 | 服务器连接 ID |
| `path` | 是 | 远程目录路径 |
文件列表返回字段:
| 字段 | 说明 |
|---|---|
| `name` | 文件名 |
| `path` | 完整路径 |
| `type` | `FILE``DIRECTORY``LINK` |
| `size` | 文件大小 |
| `permissions` | 权限字符串 |
| `modifiedTime` | 修改时间 |
下载接口直接写入 `HttpServletResponse`。下载文件名沿用远程文件名,不追加日期;仓库“导出或生成文件追加日期”的规则适用于后端生成或导出文件,本功能是下载远程已有文件,不改变原文件名。
### 7.3 终端 WebSocket
终端连接:
```text
WebSocket /deploy/terminal?serverId={serverId}
```
前端发送输入:
```json
{
"type": "input",
"data": "ls -la\n"
}
```
前端发送窗口大小:
```json
{
"type": "resize",
"cols": 120,
"rows": 30
}
```
后端输出:
```json
{
"type": "output",
"data": "total 20\r\n..."
}
```
后端状态:
```json
{
"type": "status",
"status": "CONNECTED"
}
```
异常消息:
```json
{
"type": "error",
"message": "SSH连接失败"
}
```
## 8. 参数校验
后端至少补充以下校验:
- 服务器名称不能为空。
- 主机地址不能为空。
- SSH 端口范围为 `1-65535`
- 用户名不能为空。
- 新增连接时密码不能为空。
- 编辑连接时 `id` 必须存在。
- 删除连接时 `id` 必须存在。
- 同一主机、端口、用户名组合不建议重复保存。
- 文件路径不能为空。
- 文件上传目标必须是远程目录。
- 下载目标必须是远程普通文件。
- 删除路径不能为空,不能删除空路径或根目录 `/`
- 新建目录名称不能为空,不能包含路径分隔符。
## 9. 安全与资源控制
安全规则:
- 密码不明文落盘。
- 接口返回不包含密码。
- 日志不打印密码、终端输入内容、文件内容。
- 终端不保存命令历史。
- 文件路径需要做基础规范化,避免空路径、非法路径和目录穿越。
- 下载只允许下载普通文件。
资源规则:
- SSH 连接测试设置连接超时,例如 5 秒。
- SFTP 操作每次请求创建短连接,操作完成后释放。
- 终端会话保持长连接,关闭 WebSocket 后释放 SSH Session 和 Channel。
- 终端会话设置空闲超时,默认 30 分钟。
- 本期每台服务器最多保留一个终端会话。
## 10. 依赖建议
后续实现 SSH/SFTP 时建议优先选择 Java 8 可用、项目易接入的 SSH 客户端库,例如 JSch 或 sshj。
选择标准:
- 支持 SSH 密码登录。
- 支持 SFTP 文件操作。
- 支持 Shell Channel。
- 能在 Spring Boot 2.3 和 Java 8 下稳定使用。
最终依赖需要写入 `system-ops/deploy/pom.xml`,不影响其他模块。
## 11. 错误处理
连接测试需要区分常见错误:
| 场景 | 返回说明 |
|---|---|
| 主机不可达 | 连接服务器失败 |
| 端口不通 | SSH端口连接失败 |
| 账号或密码错误 | SSH认证失败 |
| SFTP 打开失败 | 文件通道打开失败 |
| 终端打开失败 | Shell通道打开失败 |
接口层仍使用项目现有 `HttpResult``CommonResponseEnum` 风格。具体错误文案由 Service 返回给 Controller不新增全局异常体系。
## 12. 验证方式
默认不执行 Maven 编译、打包、测试命令。后续实现完成后按以下方式验证:
- 检查 `deploy` 新增代码只位于 `system-ops/deploy`
- 新增连接后,接口返回和 JSON 文件内容一致。
- 编辑连接时密码留空不会覆盖原密码。
- 删除连接后JSON 文件同步移除对应记录。
- 查询接口不返回密码。
- JSON 文件中密码不是明文。
- 测试连接能识别成功、主机不可达、端口不通、账号密码错误。
- 文件列表能展示远程目录内容。
- 上传文件后远程目录可见。
- 下载普通文件内容与远程文件一致。
- 删除文件或目录后远程路径不存在。
- 新建目录后远程路径存在。
- 终端能打开 Linux Shell执行 `pwd``ls -la``mysql --version` 等基础命令。
- 关闭终端后,后端 SSH 会话被释放。
## 13. 后续扩展
后续如需求增加,可以在当前方案基础上扩展:
- SSH 私钥登录。
- 多终端 Tab。
- 命令审计和历史记录。
- 命令黑名单或审批。
- 部署脚本编排。
- 文件批量上传和批量下载。
- Windows WinRM 或 PowerShell Remoting。
这些能力不进入本期实现,避免当前 `deploy` 模块从基础入口一次扩张为完整运维平台。