添加.gitignore,忽略build目录
This commit is contained in:
parent
c8612dee96
commit
f309e2d576
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
# Build directory
|
||||
build/
|
||||
Binary file not shown.
@ -1,67 +0,0 @@
|
||||
╔══════════════════════════════════════════════════════════════╗
|
||||
║ 3588AdminBackend 离线部署包 - 快速安装指南 ║
|
||||
╚══════════════════════════════════════════════════════════════╝
|
||||
|
||||
【系统要求】
|
||||
- Ubuntu 22.04.5 LTS (x86_64)
|
||||
- root 权限
|
||||
|
||||
【重要说明】
|
||||
✓ 本部署包已包含静态编译的二进制文件
|
||||
✓ 目标机器无需安装 Go 运行时
|
||||
✓ 无需互联网连接(纯离线安装)
|
||||
✓ 二进制文件在 Windows 上交叉编译生成
|
||||
|
||||
【安装步骤】
|
||||
|
||||
1. 上传部署包到 Ubuntu 服务器
|
||||
scp -r 3588AdminBackend-离线部署包-20260225.tar.gz user@ubuntu-server:/tmp/
|
||||
|
||||
2. 解压部署包
|
||||
tar -xzf 3588AdminBackend-离线部署包-20260225.tar.gz
|
||||
cd 3588AdminBackend-离线部署包-20260225/
|
||||
|
||||
3. 执行安装
|
||||
sudo ./scripts/3588admin install
|
||||
|
||||
4. 修改配置
|
||||
sudo nano /opt/3588admin/config/managerd.json
|
||||
|
||||
重点修改:
|
||||
- agent_token: 修改为安全的随机字符串
|
||||
- listen: 如需外部访问改为 "0.0.0.0:18080"
|
||||
|
||||
5. 启动服务
|
||||
sudo 3588admin start
|
||||
|
||||
6. 验证安装
|
||||
sudo 3588admin status
|
||||
|
||||
【常用命令】
|
||||
3588admin start - 启动服务
|
||||
3588admin stop - 停止服务
|
||||
3588admin status - 查看状态
|
||||
3588admin restart - 重启服务
|
||||
3588admin upgrade - 升级服务
|
||||
3588admin uninstall - 卸载服务
|
||||
3588admin check - 检查环境
|
||||
|
||||
【快捷命令】
|
||||
3588admin-start - 启动服务
|
||||
3588admin-stop - 停止服务
|
||||
3588admin-status - 查看状态
|
||||
|
||||
【文件位置】
|
||||
安装目录: /opt/3588admin
|
||||
配置文件: /opt/3588admin/config/managerd.json
|
||||
日志文件: /opt/3588admin/logs/managerd.log
|
||||
|
||||
【问题排查】
|
||||
1. 查看日志: tail -f /opt/3588admin/logs/managerd.log
|
||||
2. 检查配置: python3 -m json.tool /opt/3588admin/config/managerd.json
|
||||
3. 检查端口: sudo netstat -tlnp | grep managerd
|
||||
|
||||
【防火墙】
|
||||
sudo ufw allow 18080/tcp # HTTP API
|
||||
sudo ufw allow 35688/udp # UDP 发现
|
||||
|
||||
@ -1,6 +0,0 @@
|
||||
3588AdminBackend 离线部署包
|
||||
版本: 1.0.0
|
||||
构建时间: 2026-02-25 17:58:38
|
||||
Go版本: go version go1.26.0 windows/amd64
|
||||
目标系统: Ubuntu 22.04.5 LTS x86_64
|
||||
构建主机: DESKTOP-P5Q39KV (Windows)
|
||||
Binary file not shown.
@ -1,8 +0,0 @@
|
||||
{
|
||||
"listen": "0.0.0.0:18080",
|
||||
"discovery_port": 35688,
|
||||
"discovery_timeout_ms": 1200,
|
||||
"offline_after_ms": 10000,
|
||||
"agent_token": "CHANGE_ME",
|
||||
"concurrency": 5
|
||||
}
|
||||
@ -1,371 +0,0 @@
|
||||
# 设备端远程管理接口清单表(V1:对外 rk3588-agent;对内 media-server)
|
||||
|
||||
> 目标:供管理端(Go)与设备端联调对照。
|
||||
>
|
||||
> 约定:
|
||||
> - 对外:`rk3588-agent` HTTP 端口默认 `9100`(可配置),UDP 发现端口默认 `35688`。
|
||||
> - 对内:`media-server` 继续提供现有 `/api/*`(默认 9000),由 agent 本机调用。
|
||||
|
||||
---
|
||||
|
||||
## 0. 通用规范
|
||||
|
||||
### 0.1 基础 URL
|
||||
- Agent Base: `http://<device_ip>:<agent_port>`
|
||||
- Media-server Base(仅 agent 使用): `http://127.0.0.1:<media_port>`
|
||||
|
||||
### 0.2 鉴权(agent 对外)
|
||||
- Header:`X-RK-Token: <token>`
|
||||
- **必须鉴权**:所有写接口(PUT/POST 会改变设备状态或写盘)
|
||||
- **读接口**:默认可不鉴权;若 `agent.require_token_for_read=true` 则也必须鉴权
|
||||
|
||||
### 0.3 统一响应格式
|
||||
- 成功(通用):`{"ok":true}`
|
||||
- 失败(通用):`{"error":"<message>"}`(与现有 `ErrorJson()` 风格一致)
|
||||
|
||||
### 0.4 统一错误码/HTTP 状态(agent 对外)
|
||||
agent 不要求返回结构化 error_code(保持 `{"error":...}`),但**要求 HTTP 状态码语义稳定**:
|
||||
|
||||
| 场景 | HTTP | error.message 示例 |
|
||||
|---|---:|---|
|
||||
| 未鉴权/Token 错误/缺失 | 401 | `unauthorized` |
|
||||
| JSON 解析失败 / 字段缺失 / 校验失败 | 400 | `invalid json: ...` / `validation failed: ...` |
|
||||
| 资源不存在 | 404 | `not found` |
|
||||
| 方法不允许 | 405 | `method not allowed` |
|
||||
| 冲突(如 node_id 不唯一等) | 409 | `... not unique ...` |
|
||||
| 写盘失败/内部异常/reload 崩溃性失败 | 500 | `internal error: ...` |
|
||||
| 上传过大 | 413(推荐)或 400 | `payload too large` |
|
||||
|
||||
### 0.5 端口与协议
|
||||
- UDP 发现:`35688/udp`(可配置)
|
||||
- Agent HTTP:`9100/tcp`(默认,可配置)
|
||||
- Media-server HTTP:`9000/tcp`(默认,可配置)
|
||||
|
||||
---
|
||||
|
||||
## 1. UDP 发现协议(Option A)
|
||||
|
||||
### 1.1 Discover 请求(manager → broadcast)
|
||||
**发送目标**:同网段广播地址 `255.255.255.255:35688` 或各网卡广播地址
|
||||
|
||||
**数据格式**:两行 UTF-8 文本
|
||||
|
||||
Line1(固定魔法串):
|
||||
```
|
||||
RK3588SYS_DISCOVERY_V1
|
||||
```
|
||||
|
||||
Line2(JSON):
|
||||
```json
|
||||
{"type":"discover","req_id":"<uuid>","reply_port":0}
|
||||
```
|
||||
|
||||
字段:
|
||||
- `type`: 固定 `discover`
|
||||
- `req_id`: 管理端生成 UUID,用于匹配回复
|
||||
- `reply_port`: 保留字段(V1 可固定 0)
|
||||
|
||||
### 1.2 Discover 回复(device → manager 单播)
|
||||
**发送目标**:请求报文 source ip:source port
|
||||
|
||||
两行文本:
|
||||
|
||||
Line1:
|
||||
```
|
||||
RK3588SYS_DISCOVERY_V1
|
||||
```
|
||||
|
||||
Line2(JSON):
|
||||
```json
|
||||
{
|
||||
"type":"discover_reply",
|
||||
"req_id":"<uuid>",
|
||||
"device_id":"rk3588-...",
|
||||
"device_name":"rk3588-cam-01",
|
||||
"hostname":"rk3588",
|
||||
"ip":"10.0.0.21",
|
||||
"agent_port":9100,
|
||||
"media_port":9000,
|
||||
"version":"0.0.0-dev",
|
||||
"git_sha":"e5894c2",
|
||||
"uptime_sec":12345
|
||||
}
|
||||
```
|
||||
|
||||
字段说明:
|
||||
- `device_id`: 稳定唯一(优先 `/etc/machine-id`,否则 MAC/序列号;最后 fallback 生成并落盘)
|
||||
- `device_name`: 可配置的人类可读名称(agent 配置 `device_name`)
|
||||
- `agent_port`: agent HTTP 端口
|
||||
- `media_port`: media-server HTTP 端口(用于调试/展示;管理端可不直连)
|
||||
|
||||
---
|
||||
|
||||
## 2. 设备信息(agent 对外)
|
||||
|
||||
### 2.1 `GET /v1/info`
|
||||
用途:设备列表/详情页展示、联调确认端口/版本/配置路径。
|
||||
|
||||
**Auth**:读接口(见 0.2)
|
||||
|
||||
Response 200:
|
||||
```json
|
||||
{
|
||||
"device_id":"rk3588-...",
|
||||
"device_name":"rk3588-cam-01",
|
||||
"hostname":"rk3588",
|
||||
"ip":"10.0.0.21",
|
||||
"agent_port":9100,
|
||||
"media_port":9000,
|
||||
"version":"0.0.0-dev",
|
||||
"git_sha":"e5894c2",
|
||||
"config_path":"/etc/rk3588sys/config.json",
|
||||
"last_good_path":"/etc/rk3588sys/config.json.last_good.json",
|
||||
"uptime_sec":12345
|
||||
}
|
||||
```
|
||||
|
||||
失败:401/500 + `{"error":"..."}`
|
||||
|
||||
---
|
||||
|
||||
## 3. 配置下发(agent 对外)
|
||||
|
||||
### 3.1 `PUT /v1/config`
|
||||
用途:管理端上传完整 root config(可含 templates/instances),agent 原子写盘后触发 `media-server` reload。
|
||||
|
||||
**Auth**:必须(401)
|
||||
|
||||
Headers:
|
||||
- `Content-Type: application/json`
|
||||
- `X-RK-Token: ...`
|
||||
|
||||
Body:root config JSON
|
||||
|
||||
agent 处理步骤(必须满足):
|
||||
1) 解析 JSON(语法有效即可;语义校验交由 media-server reload)
|
||||
2) 原子写入 `config_path`
|
||||
3) 调用 media-server:`POST /api/config/reload`
|
||||
4) 若 reload 失败:调用 media-server:`POST /api/config/rollback`,并返回 500(包含 reload/rollback 错误信息)
|
||||
|
||||
Response 200:
|
||||
```json
|
||||
{"ok":true}
|
||||
```
|
||||
|
||||
失败:
|
||||
- 400:JSON 解析失败
|
||||
- 500:写盘失败 / reload 失败(已尝试 rollback)
|
||||
|
||||
---
|
||||
|
||||
## 4. 模型管理(agent 对外)
|
||||
|
||||
### 4.1 `PUT /v1/models/{name}`
|
||||
用途:上传模型文件并落盘,维护 manifest,返回可引用的 `path`。
|
||||
|
||||
**Auth**:必须(401)
|
||||
|
||||
Path params:
|
||||
- `name`: string(建议仅允许 `[A-Za-z0-9._-]`,超出则 400)
|
||||
|
||||
Headers:
|
||||
- `Content-Type: application/octet-stream`
|
||||
- `Content-Length: <n>`(必须)
|
||||
- `X-RK-Token: ...`
|
||||
- `X-Model-Sha256: <hex>`(可选;若存在必须匹配实际 sha256,否则 400)
|
||||
|
||||
Body:二进制文件(建议限制扩展名白名单 `.rknn`;V1 可由 name 或内容类型控制)
|
||||
|
||||
Response 200:
|
||||
```json
|
||||
{
|
||||
"ok": true,
|
||||
"name": "yolov5s-640",
|
||||
"sha256": "...",
|
||||
"path": "/opt/rk3588sys/models/files/yolov5s-640__abcd.rknn",
|
||||
"size": 12345678
|
||||
}
|
||||
```
|
||||
|
||||
失败:
|
||||
- 400:缺 Content-Length / name 非法 / sha256 不匹配
|
||||
- 413(推荐)或 400:超过 `max_upload_mb`
|
||||
- 500:写盘失败/manifest 更新失败
|
||||
|
||||
### 4.2 `GET /v1/models`
|
||||
用途:列出设备端已有模型。
|
||||
|
||||
**Auth**:读接口(见 0.2)
|
||||
|
||||
Response 200:
|
||||
```json
|
||||
{
|
||||
"items": [
|
||||
{
|
||||
"name": "yolov5s-640",
|
||||
"sha256": "...",
|
||||
"path": "/opt/rk3588sys/models/files/...",
|
||||
"size": 123,
|
||||
"mtime_ms": 1730000000000
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
失败:500 + `{"error":"..."}`
|
||||
|
||||
---
|
||||
|
||||
## 5. 业务图热更新/回滚(agent 对外)
|
||||
|
||||
### 5.1 `POST /v1/media-server/reload`
|
||||
用途:触发本机 media-server `POST /api/config/reload`。
|
||||
|
||||
**Auth**:必须(401)
|
||||
|
||||
Response 200:`{"ok":true}`
|
||||
|
||||
失败:500 + `{"error":"..."}`
|
||||
|
||||
### 5.2 `POST /v1/media-server/rollback`
|
||||
用途:触发本机 media-server `POST /api/config/rollback`。
|
||||
|
||||
**Auth**:必须(401)
|
||||
|
||||
Response 200:`{"ok":true}`
|
||||
|
||||
失败:500 + `{"error":"..."}`
|
||||
|
||||
### 5.3 `PUT /v1/media-server/configs/{name}`
|
||||
用途:上传 media-server 配置文件到 `agent.media_server_process.configs_dir`。
|
||||
|
||||
批量上传:对不同文件名重复调用该接口即可。
|
||||
|
||||
**Auth**:必须(401)
|
||||
|
||||
Headers:
|
||||
- `Content-Type: application/json`
|
||||
- `X-RK-Token: ...`
|
||||
|
||||
Path params:
|
||||
- `name`: string(仅允许 `[A-Za-z0-9._-]`,禁止 `/`、`\\`、`..`;若无 `.json` 后缀则自动追加)
|
||||
|
||||
Body:media-server 配置 JSON
|
||||
|
||||
Response 200:
|
||||
```json
|
||||
{
|
||||
"ok": true,
|
||||
"name": "cam1.json",
|
||||
"path": "/opt/rk3588sys/configs/cam1.json",
|
||||
"size": 1234,
|
||||
"mtime_ms": 1730000000000
|
||||
}
|
||||
```
|
||||
|
||||
失败:
|
||||
- 400:name 非法 / Content-Type 非 application/json / JSON 无效 / 空 body
|
||||
- 401:unauthorized
|
||||
- 413:超过 `max_upload_mb`
|
||||
- 501:`configs_dir` 未配置
|
||||
- 500:写盘失败
|
||||
|
||||
## 6. 主程序进程控制(agent 对外)
|
||||
|
||||
> 说明:该能力用于“启动/重启/关闭主程序(media-server)并选择加载哪个配置文件”。
|
||||
>
|
||||
> agent 启动 media-server 时会显式传入:`--config <resolved_config_path>`,因此不依赖 media-server 内部默认配置。
|
||||
>
|
||||
> 路径说明:
|
||||
> - `agent.media_server_process` 下的 `exec_path/work_dir/configs_dir/pid_file` 支持绝对或相对路径;若为相对路径,则以 agent 启动参数 `--config <agent_config_path>` 的**配置文件所在目录**为基准解析。
|
||||
> - `agent.config_path` 建议使用**绝对路径**;若使用相对路径:
|
||||
> - `PUT /v1/config` 写盘时,以 **agent 进程当前工作目录(CWD)** 为基准;
|
||||
> - 通过 `/v1/media-server/start|restart`(缺省 config)启动时,会把该相对路径原样传给 media-server,最终以 **media_server_process.work_dir** 为基准解析。
|
||||
|
||||
### 6.1 `POST /v1/media-server/start`
|
||||
用途:启动本机 media-server(若已运行则幂等返回 ok;若已运行但 config 不同则 409)。
|
||||
|
||||
**Auth**:必须(401)
|
||||
|
||||
Body(可选,JSON):
|
||||
```json
|
||||
{"config":"cam1"}
|
||||
```
|
||||
|
||||
说明:若请求 body 非空,则必须带 `Content-Type: application/json`;若 body 为空,可不带该 header。
|
||||
|
||||
`config` 解析规则:
|
||||
- 为空/缺省:使用 `agent.config_path`
|
||||
- 非空:只允许文件名/配置名(禁止包含 `/`、`\\`、`..`);若不带扩展名自动补 `.json`;最终从 `agent.media_server_process.configs_dir` 下解析为 `<configs_dir>/<config>.json`
|
||||
|
||||
Response 200:
|
||||
```json
|
||||
{"ok":true,"running":true,"pid":1234,"config_path":"/etc/rk3588sys/config.json"}
|
||||
```
|
||||
|
||||
失败:
|
||||
- 400:config 不合法 / config 文件不存在
|
||||
- 409:已运行但 config 不同(提示使用 restart)
|
||||
- 501:未启用进程控制(agent 配置 `agent.media_server_process.enable=false` 或未配置)
|
||||
- 500:启动失败 / 写 pidfile 失败
|
||||
|
||||
### 6.2 `POST /v1/media-server/restart`
|
||||
用途:重启本机 media-server(可切换 config)。
|
||||
|
||||
**Auth**:必须(401)
|
||||
|
||||
Body(可选,JSON):
|
||||
```json
|
||||
{"config":"cam1"}
|
||||
```
|
||||
|
||||
说明:若请求 body 非空,则必须带 `Content-Type: application/json`;若 body 为空,可不带该 header。
|
||||
|
||||
Response 200:
|
||||
```json
|
||||
{"ok":true,"running":true,"pid":1234,"config_path":"/home/orangepi/Desktop/OrangePi3588Media/configs/cam1.json"}
|
||||
```
|
||||
|
||||
失败:
|
||||
- 400:config 不合法 / config 文件不存在
|
||||
- 501:未启用进程控制
|
||||
- 500:停止/启动失败
|
||||
|
||||
### 6.3 `POST /v1/media-server/stop`
|
||||
用途:停止本机 media-server(未运行也返回 ok)。
|
||||
|
||||
**Auth**:必须(401)
|
||||
|
||||
Response 200:
|
||||
```json
|
||||
{"ok":true,"running":false,"pid":1234,"config_path":"/etc/rk3588sys/config.json"}
|
||||
```
|
||||
|
||||
失败:
|
||||
- 501:未启用进程控制
|
||||
- 500:停止失败
|
||||
|
||||
### 6.4 `GET /v1/media-server/status`
|
||||
用途:查询本机 media-server 是否在运行(以 agent 的 pidfile 记录为准)。
|
||||
|
||||
**Auth**:读接口(见 0.2)
|
||||
|
||||
Response 200:
|
||||
```json
|
||||
{"ok":true,"running":true,"pid":1234,"config_path":"/etc/rk3588sys/config.json"}
|
||||
```
|
||||
|
||||
失败:
|
||||
- 501:未启用进程控制
|
||||
- 500:读取 pidfile/进程存活检测失败
|
||||
|
||||
## 7. 只读代理接口(agent 对外,推荐管理端统一走 agent)
|
||||
|
||||
### 7.1 `GET /v1/graphs`
|
||||
代理 media-server:`GET /api/graphs`
|
||||
|
||||
### 7.2 `GET /v1/graphs/{name}`
|
||||
代理 media-server:`GET /api/graphs/{name}`
|
||||
|
||||
### 7.3 `GET /v1/logs/recent?limit=200`
|
||||
代理 media-server:`GET /api/logs/recent?limit=...`
|
||||
@ -1,196 +0,0 @@
|
||||
# PRD ③ 管理端后端(Go managerd)V1
|
||||
|
||||
## 1. 目标与运行方式
|
||||
|
||||
- 提供本机 HTTP API 给 React UI 使用。
|
||||
- 负责 UDP 广播发现(Option A),维护设备缓存与在线状态。
|
||||
- 通过设备端 `rk3588-agent` 完成配置/模型等运维操作,并可通过 agent 代理读取 graphs/logs。
|
||||
- 支持批量任务(并发、进度、失败原因)并通过 SSE 推送。
|
||||
|
||||
运行:单可执行 `managerd`,默认监听 `127.0.0.1:18080`(可配置)。
|
||||
|
||||
## 2. 外部依赖与约束
|
||||
|
||||
- Go 版本:>= 1.22(建议)
|
||||
- 标准库优先;Web 框架可选 `chi`/`gin`(建议 chi + net/http)。
|
||||
- 不需要数据库(V1 用内存 + 可选本地 JSON 持久化)。
|
||||
|
||||
## 3. 模块划分
|
||||
|
||||
### 3.1 Discovery
|
||||
|
||||
- 向所有可用网卡的广播地址发送 UDP discover。
|
||||
- 监听本地 UDP socket 收集 replies(时间窗默认 1200ms)。
|
||||
- 去重规则:按 `device_id` 去重,以最新 reply 为准。
|
||||
|
||||
### 3.2 Device Registry
|
||||
|
||||
- 内存缓存:
|
||||
- `device_id -> {ip, agent_port, media_port, device_name, version, git_sha, last_seen_ms, online}`
|
||||
- 定时刷新(可配置间隔):对 online 设备拉取 `GET /v1/graphs`(agent 代理),更新摘要。
|
||||
- Offline 规则:超过 `offline_after_ms`(如 10000ms)未见到,则标记离线。
|
||||
|
||||
### 3.3 Device Client
|
||||
|
||||
- 统一超时:connect 1s、overall 3s(可配置)。
|
||||
- 统一错误包装:返回 `error_code + message + device_id`。
|
||||
- Token:
|
||||
- 全局默认 token(V1)
|
||||
- 可预留 per-device token(P1)
|
||||
|
||||
### 3.4 Templates/Config Builder
|
||||
|
||||
- 模板库来源:
|
||||
- V1:managerd 内置(embed)或本地 `templates/` 目录读取
|
||||
- 返回前端表单 schema:V1 允许手工维护(避免解析占位符带来的不确定性)。
|
||||
- 生成 root config:基于模板与 params,产出 `{global,templates,instances}`。
|
||||
|
||||
### 3.5 Task Runner
|
||||
|
||||
- 任务类型:
|
||||
- `config_apply`(对 N 台设备下发 config)
|
||||
- `reload`
|
||||
- `rollback`
|
||||
- `model_upload`(V1 可先做单设备;批量后续)
|
||||
- 并发控制:默认 5(可配置)。
|
||||
- 状态:`pending/running/success/failed`(逐设备与整体)。
|
||||
- 推送:SSE `GET /api/tasks/:id/events`。
|
||||
|
||||
## 4. managerd 对前端 API 规格(V1)
|
||||
|
||||
### 4.1 Discovery
|
||||
|
||||
#### `POST /api/discovery/search`
|
||||
|
||||
Request:
|
||||
|
||||
```json
|
||||
{ "timeout_ms": 1200 }
|
||||
```
|
||||
|
||||
Response:
|
||||
|
||||
```json
|
||||
{ "items": [ {"device_id":"...","ip":"...","agent_port":9100,"media_port":9000,"device_name":"...","version":"...","git_sha":"..."} ] }
|
||||
```
|
||||
|
||||
### 4.2 Devices
|
||||
|
||||
#### `GET /api/devices`
|
||||
|
||||
Response:
|
||||
|
||||
```json
|
||||
{ "items": [ {"device_id":"...","online":true,"last_seen_ms":0,"ip":"...","agent_port":9100,"media_port":9000,"device_name":"...","version":"...","git_sha":"...","graphs":[...]} ] }
|
||||
```
|
||||
|
||||
#### `GET /api/devices/:id`
|
||||
|
||||
Response:包含 `info`、`graphs_summary`、`last_seen`。
|
||||
|
||||
### 4.3 Device actions(代理调用)
|
||||
|
||||
以下全部通过 agent:
|
||||
|
||||
- `POST /api/devices/:id/reload` → agent `POST /v1/media-server/reload`
|
||||
- `POST /api/devices/:id/rollback` → agent `POST /v1/media-server/rollback`
|
||||
- `GET /api/devices/:id/graphs` → agent `GET /v1/graphs`
|
||||
- `GET /api/devices/:id/graphs/:name` → agent `GET /v1/graphs/{name}`
|
||||
- `GET /api/devices/:id/logs?limit=200` → agent `GET /v1/logs/recent?limit=200`
|
||||
|
||||
### 4.4 Config apply
|
||||
|
||||
#### `POST /api/devices/:id/config/apply`
|
||||
|
||||
Request:
|
||||
|
||||
```json
|
||||
{ "config": { } }
|
||||
```
|
||||
|
||||
Behavior:调用 agent `PUT /v1/config`。
|
||||
|
||||
### 4.5 Model upload
|
||||
|
||||
#### `POST /api/devices/:id/models/upload`
|
||||
|
||||
Request:`multipart/form-data`,字段:
|
||||
|
||||
- `name`: string
|
||||
- `file`: binary
|
||||
|
||||
Behavior:读取文件流,转发为 agent `PUT /v1/models/{name}`(raw body)。
|
||||
|
||||
### 4.6 Templates
|
||||
|
||||
- `GET /api/templates`
|
||||
- `GET /api/templates/:name`
|
||||
|
||||
### 4.7 Tasks
|
||||
|
||||
#### `POST /api/tasks`
|
||||
|
||||
Request:
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "config_apply",
|
||||
"device_ids": ["..."],
|
||||
"payload": { "config": {} }
|
||||
}
|
||||
```
|
||||
|
||||
Response:
|
||||
|
||||
```json
|
||||
{ "task_id": "..." }
|
||||
```
|
||||
|
||||
#### `GET /api/tasks/:id/events` (SSE)
|
||||
|
||||
Event `device_update` data:
|
||||
|
||||
```json
|
||||
{ "device_id":"...","status":"running|success|failed","progress":0.0,"error":"" }
|
||||
```
|
||||
|
||||
## 5. 错误处理规范(managerd → 前端)
|
||||
|
||||
- 成功:2xx + `{"ok":true}` 或正常业务 JSON
|
||||
- 失败:4xx/5xx +
|
||||
|
||||
```json
|
||||
{ "error": { "code": "...", "message": "...", "device_id": "...", "detail": "..." } }
|
||||
```
|
||||
|
||||
建议错误码:
|
||||
|
||||
- `DISCOVERY_FAILED`
|
||||
- `DEVICE_NOT_FOUND`
|
||||
- `DEVICE_OFFLINE`
|
||||
- `DEVICE_HTTP_ERROR`
|
||||
- `DEVICE_TIMEOUT`
|
||||
- `TASK_NOT_FOUND`
|
||||
- `VALIDATION_ERROR`
|
||||
|
||||
## 6. 配置文件(managerd)建议
|
||||
|
||||
`managerd.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"listen": "127.0.0.1:18080",
|
||||
"discovery_port": 35688,
|
||||
"discovery_timeout_ms": 1200,
|
||||
"offline_after_ms": 10000,
|
||||
"agent_token": "CHANGE_ME",
|
||||
"concurrency": 5
|
||||
}
|
||||
```
|
||||
|
||||
## 7. 验收标准
|
||||
|
||||
1. Search 可发现设备并更新 registry;离线判断正确。
|
||||
2. 可通过 agent 读取 graphs/logs(`GET /v1/graphs`、`GET /v1/logs/recent`)。
|
||||
3. 单设备 `config/apply`、`reload`、`rollback` 可用,错误可定位。
|
||||
4. 批量 `config_apply` 任务可并发执行并通过 SSE 输出逐台结果。
|
||||
@ -1,592 +0,0 @@
|
||||
# 3588AdminBackend 离线部署文档
|
||||
|
||||
> **目标环境**: Ubuntu 22.04.5 LTS (离线环境,无法连接互联网)
|
||||
> **部署方式**: 在 Windows 上交叉编译,上传安装包到 Ubuntu 进行离线部署
|
||||
> **版本**: V2.1 (Windows 构建版)
|
||||
|
||||
---
|
||||
|
||||
## 目录
|
||||
|
||||
1. [部署概述](#1-部署概述)
|
||||
2. [准备环境(Windows)](#2-准备环境windows)
|
||||
3. [构建步骤(Windows)](#3-构建步骤windows)
|
||||
4. [离线安装(Ubuntu)](#4-离线安装ubuntu)
|
||||
5. [验证与启动](#5-验证与启动)
|
||||
6. [常见问题排查](#6-常见问题排查)
|
||||
|
||||
---
|
||||
|
||||
## 1. 部署概述
|
||||
|
||||
### 1.1 项目简介
|
||||
|
||||
3588AdminBackend 是 Orange Pi 3588 媒体服务器的后台管理端,提供以下功能:
|
||||
|
||||
- 设备发现与注册管理
|
||||
- 设备配置下发与批量任务管理
|
||||
- 代理调用设备端 API
|
||||
- SSE 实时任务进度推送
|
||||
|
||||
### 1.2 技术栈
|
||||
|
||||
| 组件 | 版本 | 说明 |
|
||||
|------|------|------|
|
||||
| Go | 1.23+ | **编译环境(仅 Windows 构建机需要)** |
|
||||
| chi | v5.2.3 | Web 框架(已静态编译到二进制) |
|
||||
| cors | v1.2.2 | CORS 中间件(已静态编译到二进制) |
|
||||
| uuid | v1.6.0 | UUID 生成库(已静态编译到二进制) |
|
||||
|
||||
> **注意**: Go 编译生成的是**静态链接的二进制文件**,目标机器(Ubuntu 生产环境)**不需要**安装 Go 运行时,只需要 Linux 内核即可运行。
|
||||
|
||||
### 1.3 部署流程概览
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────────────────────────┐
|
||||
│ Windows(构建环境) │
|
||||
│ ┌──────────────────────────────────────────────────────────────┐ │
|
||||
│ │ 1. 安装 Go 1.23+ │ │
|
||||
│ │ 2. 运行 build-windows.ps1 │ │
|
||||
│ │ 3. 生成 3588AdminBackend-离线部署包-YYYYMMDD.tar.gz │ │
|
||||
│ └──────────────────────────────────────────────────────────────┘ │
|
||||
└──────────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼ (上传到 Ubuntu 服务器)
|
||||
┌──────────────────────────────────────────────────────────────────────┐
|
||||
│ Ubuntu(生产环境) │
|
||||
│ ┌──────────────────────────────────────────────────────────────┐ │
|
||||
│ │ 无需 Go 运行时!直接运行编译好的静态二进制文件 │ │
|
||||
│ │ - tar -xzf 3588AdminBackend-离线部署包-*.tar.gz │ │
|
||||
│ │ - sudo ./scripts/3588admin install │ │
|
||||
│ │ - sudo ./scripts/3588admin start │ │
|
||||
│ └──────────────────────────────────────────────────────────────┘ │
|
||||
└──────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. 准备环境(Windows)
|
||||
|
||||
### 2.1 系统要求
|
||||
|
||||
- **操作系统**: Windows 10/11 或 Windows Server 2019+
|
||||
- **磁盘空间**: 至少 1GB 可用空间
|
||||
- **Go 版本**: 1.23.3 或更高
|
||||
- **网络**: 可访问互联网(下载 Go 依赖)
|
||||
|
||||
### 2.2 安装 Go 编译环境
|
||||
|
||||
1. **下载 Go 安装包**
|
||||
- 访问 https://go.dev/dl/
|
||||
- 下载 `go1.23.3.windows-amd64.msi`
|
||||
|
||||
2. **安装 Go**
|
||||
- 双击 MSI 文件,按向导安装
|
||||
- 默认安装到 `C:\Program Files\Go\`
|
||||
- 安装程序会自动配置 PATH
|
||||
|
||||
3. **验证安装**
|
||||
```powershell
|
||||
# 打开 PowerShell 或 CMD
|
||||
go version
|
||||
# 输出: go version go1.23.3 windows/amd64
|
||||
```
|
||||
|
||||
### 2.3 准备项目源码
|
||||
|
||||
将项目源码复制到 Windows 机器上,例如:
|
||||
```
|
||||
C:\Users\YourName\3588AdminBackend\
|
||||
```
|
||||
|
||||
目录结构应包含:
|
||||
```
|
||||
3588AdminBackend/
|
||||
├── cmd/
|
||||
│ └── managerd/
|
||||
├── internal/
|
||||
├── scripts/
|
||||
│ └── deploy/
|
||||
│ ├── 3588admin # 管理脚本
|
||||
│ ├── 3588admin.service # Systemd 服务
|
||||
│ └── build-windows.ps1 # Windows 构建脚本
|
||||
├── templates/
|
||||
├── go.mod
|
||||
└── go.sum
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 构建步骤(Windows)
|
||||
|
||||
### 3.1 运行构建脚本
|
||||
|
||||
打开 PowerShell,进入项目目录:
|
||||
|
||||
```powershell
|
||||
# 进入项目目录
|
||||
cd C:\Users\YourName\3588AdminBackend\scripts\deploy
|
||||
|
||||
# 执行构建脚本
|
||||
.\build-windows.ps1
|
||||
```
|
||||
|
||||
或一行命令:
|
||||
```powershell
|
||||
& "C:<Users>YourName<3588AdminBackend<scripts>deploy<build-windows.ps1"
|
||||
```
|
||||
|
||||
### 3.2 构建输出
|
||||
|
||||
构建完成后,会在 `build\` 目录下生成:
|
||||
```
|
||||
3588AdminBackend-离线部署包-YYYYMMDD.tar.gz
|
||||
```
|
||||
|
||||
构建输出示例:
|
||||
```
|
||||
========== 3588AdminBackend Windows 构建 ==========
|
||||
项目目录: C:<Users>YourName<3588AdminBackend
|
||||
构建目录: C:<Users>YourName<3588AdminBackend<build
|
||||
Go 版本: go version go1.23.3 windows/amd64
|
||||
|
||||
[1/6] 清理旧构建...
|
||||
[2/6] 创建目录结构...
|
||||
[3/6] 交叉编译 Linux AMD64 版本...
|
||||
编译成功
|
||||
[4/6] 复制配置文件...
|
||||
[5/6] 复制部署脚本...
|
||||
[6/6] 复制文档...
|
||||
|
||||
打包...
|
||||
|
||||
========== 构建完成 ==========
|
||||
|
||||
输出文件:
|
||||
3588AdminBackend-离线部署包-20260225.tar.gz (12.34 MB)
|
||||
|
||||
部署包位置: C:<Users>YourName<3588AdminBackend<build<3588AdminBackend-离线部署包-20260225.tar.gz
|
||||
|
||||
使用说明:
|
||||
1. 将 3588AdminBackend-离线部署包-20260225.tar.gz 上传到 Ubuntu 服务器
|
||||
2. 解压并运行: sudo ./scripts/3588admin install
|
||||
```
|
||||
|
||||
### 3.3 手动打包(如不使用脚本)
|
||||
|
||||
如果 PowerShell 脚本执行失败,可以手动操作:
|
||||
|
||||
```powershell
|
||||
# 1. 进入项目目录
|
||||
cd C:<Users>YourName<3588AdminBackend
|
||||
|
||||
# 2. 交叉编译 Linux 版本
|
||||
$env:GOOS = "linux"
|
||||
$env:GOARCH = "amd64"
|
||||
go build -ldflags="-s -w" -o managerd-linux-amd64 .\cmd\managerd
|
||||
|
||||
# 3. 创建部署目录
|
||||
mkdir build<3588admin-deploy<bin
|
||||
mkdir build<3588admin-deploy<config
|
||||
mkdir build<3588admin-deploy<scripts
|
||||
|
||||
# 4. 复制文件
|
||||
copy managerd-linux-amd64 build<3588admin-deploy<bin<managerd
|
||||
copy scripts>deploy<3588admin build<3588admin-deploy<scripts<
|
||||
copy scripts>deploy<3588admin.service build<3588admin-deploy<scripts<
|
||||
copy managerd.json build<3588admin-deploy<config<managerd.json.example
|
||||
|
||||
# 5. 打包
|
||||
cd build
|
||||
tar -czf 3588AdminBackend-离线部署包-$(Get-Date -Format 'yyyyMMdd').tar.gz 3588admin-deploy<
|
||||
```
|
||||
|
||||
### 3.4 上传到 Ubuntu 服务器
|
||||
|
||||
使用 SCP、FTP 或任何文件传输工具将部署包上传到 Ubuntu:
|
||||
|
||||
```powershell
|
||||
# 使用 scp(如果 Windows 有 OpenSSH)
|
||||
scp .\build<3588AdminBackend-离线部署包-*.tar.gz user@ubuntu-server:/tmp/
|
||||
|
||||
# 或使用 WinSCP、FileZilla 等图形化工具
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 离线安装(Ubuntu)
|
||||
|
||||
> **环境**: Ubuntu 22.04.5 LTS,无网络连接
|
||||
|
||||
### 4.1 解压部署包
|
||||
|
||||
```bash
|
||||
# 进入上传目录
|
||||
cd /tmp
|
||||
|
||||
# 解压
|
||||
tar -xzf 3588AdminBackend-离线部署包-*.tar.gz
|
||||
|
||||
# 进入部署目录
|
||||
cd 3588AdminBackend-离线部署包-*/
|
||||
|
||||
# 查看内容
|
||||
ls -la
|
||||
```
|
||||
|
||||
### 4.2 执行安装
|
||||
|
||||
```bash
|
||||
# 检查环境(可选但推荐)
|
||||
sudo ./scripts/3588admin check
|
||||
|
||||
# 执行安装
|
||||
sudo ./scripts/3588admin install
|
||||
|
||||
# 或指定自定义安装目录
|
||||
# sudo ./scripts/3588admin install /usr/local/3588admin
|
||||
```
|
||||
|
||||
安装脚本会自动完成:
|
||||
|
||||
- 检查 root 权限
|
||||
- 复制文件到安装目录
|
||||
- 设置执行权限
|
||||
- 创建配置文件
|
||||
- 创建命令快捷方式(`3588admin-start`, `3588admin-stop`, `3588admin-status`)
|
||||
- 安装 Systemd 服务(可选)
|
||||
|
||||
### 4.3 配置 Systemd 服务(可选但推荐)
|
||||
|
||||
```bash
|
||||
# 复制服务文件
|
||||
sudo cp /opt/3588admin/scripts/3588admin.service /etc/systemd/system/
|
||||
|
||||
# 重新加载 systemd
|
||||
sudo systemctl daemon-reload
|
||||
|
||||
# 设置开机自启
|
||||
sudo systemctl enable 3588admin
|
||||
|
||||
# 启动服务
|
||||
sudo systemctl start 3588admin
|
||||
|
||||
# 查看状态
|
||||
sudo systemctl status 3588admin
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 验证与启动
|
||||
|
||||
### 5.1 修改配置文件
|
||||
|
||||
```bash
|
||||
# 编辑配置文件
|
||||
sudo nano /opt/3588admin/config/managerd.json
|
||||
```
|
||||
|
||||
**关键配置项说明**:
|
||||
|
||||
```json
|
||||
{
|
||||
"listen": "0.0.0.0:18080", // HTTP API 监听地址(0.0.0.0 允许外部访问)
|
||||
"discovery_port": 35688, // UDP 发现端口
|
||||
"discovery_timeout_ms": 1200, // 发现超时时间
|
||||
"offline_after_ms": 10000, // 设备离线判定时间
|
||||
"agent_token": "CHANGE_ME", // !!! 必须修改 !!! 与设备端通信的 Token
|
||||
"concurrency": 5 // 批量任务并发数
|
||||
}
|
||||
```
|
||||
|
||||
**配置建议**:
|
||||
|
||||
- `listen`: 如果前端通过本地访问,保持 `127.0.0.1:18080`;如果需要外部访问,改为 `0.0.0.0:18080`
|
||||
- `agent_token`: **必须修改为安全的随机字符串**,与设备端配置的 token 保持一致
|
||||
|
||||
### 5.2 启动服务
|
||||
|
||||
**方式1: 使用管理脚本(推荐)**
|
||||
|
||||
```bash
|
||||
# 启动
|
||||
sudo 3588admin start
|
||||
|
||||
# 查看状态
|
||||
sudo 3588admin status
|
||||
|
||||
# 停止
|
||||
sudo 3588admin stop
|
||||
|
||||
# 重启
|
||||
sudo 3588admin restart
|
||||
```
|
||||
|
||||
**方式2: 使用快捷命令**
|
||||
|
||||
```bash
|
||||
# 启动
|
||||
sudo 3588admin-start
|
||||
|
||||
# 查看状态
|
||||
sudo 3588admin-status
|
||||
|
||||
# 停止
|
||||
sudo 3588admin-stop
|
||||
```
|
||||
|
||||
**方式3: 使用 Systemd**
|
||||
|
||||
```bash
|
||||
sudo systemctl start 3588admin
|
||||
sudo systemctl status 3588admin
|
||||
```
|
||||
|
||||
### 5.3 验证服务
|
||||
|
||||
```bash
|
||||
# 检查进程
|
||||
ps aux | grep managerd
|
||||
|
||||
# 检查端口监听
|
||||
sudo netstat -tlnp | grep 18080
|
||||
# 或
|
||||
sudo ss -tlnp | grep 18080
|
||||
|
||||
# 测试 API
|
||||
curl http://127.0.0.1:18080/api/devices
|
||||
|
||||
# 查看日志
|
||||
tail -f /opt/3588admin/logs/managerd.log
|
||||
```
|
||||
|
||||
### 5.4 防火墙配置
|
||||
|
||||
```bash
|
||||
# 开放 HTTP API 端口(如需外部访问)
|
||||
sudo ufw allow 18080/tcp
|
||||
|
||||
# 开放 UDP 发现端口(必须)
|
||||
sudo ufw allow 35688/udp
|
||||
|
||||
# 重新加载防火墙
|
||||
sudo ufw reload
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 常见问题排查
|
||||
|
||||
### 6.1 Windows 构建失败
|
||||
|
||||
**问题**: 执行 `build-windows.ps1` 提示权限不足
|
||||
|
||||
**解决**:
|
||||
```powershell
|
||||
# 以管理员身份运行 PowerShell
|
||||
# 右键点击 PowerShell -> 以管理员身份运行
|
||||
|
||||
# 或修改执行策略(临时)
|
||||
Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process
|
||||
.\build-windows.ps1
|
||||
```
|
||||
|
||||
**问题**: `tar` 命令不存在
|
||||
|
||||
**解决**: Windows 10/11 内置 tar,如果找不到,使用 7-Zip 或其他工具手动打包。
|
||||
|
||||
### 6.2 Ubuntu 上启动失败
|
||||
|
||||
**问题**: 执行 start 命令提示启动失败
|
||||
|
||||
**排查步骤**:
|
||||
|
||||
```bash
|
||||
# 1. 检查二进制文件架构是否匹配
|
||||
file /opt/3588admin/bin/managerd
|
||||
# 应输出: ELF 64-bit LSB executable, x86-64
|
||||
|
||||
# 2. 直接运行查看错误信息
|
||||
/opt/3588admin/bin/managerd -config /opt/3588admin/config/managerd.json
|
||||
|
||||
# 3. 检查配置文件格式
|
||||
python3 -m json.tool /opt/3588admin/config/managerd.json
|
||||
```
|
||||
|
||||
### 6.3 端口被占用
|
||||
|
||||
**问题**: 提示端口 18080 已被占用
|
||||
|
||||
**解决**:
|
||||
|
||||
```bash
|
||||
# 查找占用端口的进程
|
||||
sudo lsof -i :18080
|
||||
# 或
|
||||
sudo netstat -tlnp | grep 18080
|
||||
|
||||
# 修改配置文件使用其他端口
|
||||
sudo nano /opt/3588admin/config/managerd.json
|
||||
# 修改 "listen" 为 "127.0.0.1:18081" 或其他端口
|
||||
```
|
||||
|
||||
### 6.4 无法发现设备
|
||||
|
||||
**问题**: 设备发现功能不工作
|
||||
|
||||
**排查**:
|
||||
|
||||
```bash
|
||||
# 检查 UDP 端口监听
|
||||
sudo netstat -ulnp | grep 35688
|
||||
|
||||
# 检查防火墙
|
||||
sudo ufw status | grep 35688
|
||||
|
||||
# 检查网络接口是否有权限发送广播
|
||||
# 可能需要以 root 运行
|
||||
|
||||
# 检查设备端是否配置了正确的发现端口和 token
|
||||
```
|
||||
|
||||
### 6.5 权限问题
|
||||
|
||||
**问题**: 提示 Permission denied
|
||||
|
||||
**解决**:
|
||||
|
||||
```bash
|
||||
# 修复权限
|
||||
sudo chmod +x /opt/3588admin/bin/managerd
|
||||
sudo chmod +x /opt/3588admin/scripts/3588admin
|
||||
|
||||
# 确保以 root 运行
|
||||
sudo 3588admin start
|
||||
```
|
||||
|
||||
### 6.6 日志查看
|
||||
|
||||
```bash
|
||||
# 实时查看日志
|
||||
tail -f /opt/3588admin/logs/managerd.log
|
||||
|
||||
# 查看最近 100 行
|
||||
tail -n 100 /opt/3588admin/logs/managerd.log
|
||||
|
||||
# 搜索错误信息
|
||||
grep -i error /opt/3588admin/logs/managerd.log
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 附录
|
||||
|
||||
### A. 目录结构参考
|
||||
|
||||
**Windows 构建机**:
|
||||
```
|
||||
C:<Users>YourName<3588AdminBackend<
|
||||
├── build< # 构建输出
|
||||
│ └── 3588AdminBackend-离线部署包-20260225<
|
||||
│ ├── bin<
|
||||
│ │ └── managerd # Linux 静态二进制文件
|
||||
│ ├── config<
|
||||
│ ├── scripts<
|
||||
│ │ └── 3588admin # 管理脚本
|
||||
│ ├── docs<
|
||||
│ └── README-离线安装.txt
|
||||
├── scripts>deploy<
|
||||
│ ├── 3588admin
|
||||
│ ├── 3588admin.service
|
||||
│ └── build-windows.ps1 # Windows 构建脚本
|
||||
├── cmd<
|
||||
├── internal<
|
||||
└── go.mod
|
||||
```
|
||||
|
||||
**Ubuntu 生产环境**:
|
||||
```
|
||||
/opt/3588admin/
|
||||
├── bin/
|
||||
│ └── managerd # 主程序(Windows 交叉编译生成)
|
||||
├── config/
|
||||
│ └── managerd.json # 配置文件
|
||||
├── logs/
|
||||
│ └── managerd.log # 运行日志
|
||||
├── scripts/
|
||||
│ ├── 3588admin # 统一管理脚本
|
||||
│ └── 3588admin.service # 服务文件(复制用)
|
||||
└── systemd/ # (如安装服务)
|
||||
```
|
||||
|
||||
### B. 管理脚本命令速查
|
||||
|
||||
```bash
|
||||
# 环境检查
|
||||
sudo 3588admin check
|
||||
|
||||
# 安装
|
||||
sudo 3588admin install [目录]
|
||||
|
||||
# 启动/停止/重启
|
||||
sudo 3588admin start
|
||||
sudo 3588admin stop
|
||||
sudo 3588admin restart
|
||||
|
||||
# 查看状态
|
||||
sudo 3588admin status
|
||||
|
||||
# 升级
|
||||
sudo 3588admin upgrade [目录]
|
||||
|
||||
# 卸载
|
||||
sudo 3588admin uninstall [目录]
|
||||
|
||||
# 帮助
|
||||
3588admin help
|
||||
```
|
||||
|
||||
### C. 升级步骤
|
||||
|
||||
```bash
|
||||
# 1. 停止服务
|
||||
sudo 3588admin stop
|
||||
# 或
|
||||
sudo systemctl stop 3588admin
|
||||
|
||||
# 2. 备份配置
|
||||
cp /opt/3588admin/config/managerd.json ~/managerd.json.bak
|
||||
|
||||
# 3. 在 Windows 上重新构建新版本
|
||||
# 运行 build-windows.ps1
|
||||
|
||||
# 4. 上传到 Ubuntu 并执行升级
|
||||
sudo ./scripts/3588admin upgrade
|
||||
|
||||
# 5. 验证升级
|
||||
sudo 3588admin status
|
||||
```
|
||||
|
||||
### D. 完全卸载
|
||||
|
||||
```bash
|
||||
# 方式1: 使用管理脚本
|
||||
sudo 3588admin uninstall
|
||||
|
||||
# 方式2: 手动卸载
|
||||
sudo 3588admin stop
|
||||
sudo systemctl stop 3588admin 2>/dev/null || true
|
||||
sudo systemctl disable 3588admin 2>/dev/null || true
|
||||
sudo rm -f /etc/systemd/system/3588admin.service
|
||||
sudo rm -rf /opt/3588admin
|
||||
sudo rm -f /usr/local/bin/3588admin*
|
||||
sudo systemctl daemon-reload
|
||||
|
||||
echo "卸载完成"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**文档版本**: 2.1 (Windows 构建版)
|
||||
**最后更新**: 2026-02-25
|
||||
**适用版本**: 3588AdminBackend V1.0+
|
||||
@ -1,845 +0,0 @@
|
||||
#!/bin/bash
|
||||
# 3588AdminBackend 统一管理脚本
|
||||
# 提供安装、状态、升级、卸载等功能
|
||||
|
||||
set -e
|
||||
|
||||
# 颜色定义
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m'
|
||||
|
||||
# 配置
|
||||
APP_NAME="managerd"
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
DEFAULT_INSTALL_DIR="/opt/3588admin"
|
||||
INSTALL_DIR="${DEFAULT_INSTALL_DIR}"
|
||||
PID_FILE="$INSTALL_DIR/$APP_NAME.pid"
|
||||
|
||||
# 显示帮助
|
||||
cmd_help() {
|
||||
cat << EOF
|
||||
3588AdminBackend 管理脚本
|
||||
|
||||
用法: $0 <命令> [选项]
|
||||
|
||||
命令:
|
||||
install [目录] 安装服务 (默认: /opt/3588admin)
|
||||
status 查看服务状态
|
||||
start 启动服务
|
||||
stop 停止服务
|
||||
restart 重启服务
|
||||
upgrade [目录] 升级服务 (保留配置)
|
||||
uninstall [目录] 卸载服务 (自动备份配置)
|
||||
check 检查环境是否满足运行要求
|
||||
help 显示此帮助信息
|
||||
|
||||
示例:
|
||||
$0 install # 安装到默认目录
|
||||
$0 install /usr/local/3588 # 安装到指定目录
|
||||
$0 status # 查看服务状态
|
||||
$0 upgrade # 升级到当前目录下的新版本
|
||||
$0 uninstall # 卸载并备份配置
|
||||
$0 check # 检查系统环境
|
||||
|
||||
快捷命令 (安装后可用):
|
||||
3588admin-start 启动服务
|
||||
3588admin-stop 停止服务
|
||||
3588admin-status 查看状态
|
||||
EOF
|
||||
}
|
||||
|
||||
# 检查 root 权限
|
||||
check_root() {
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
echo -e "${RED}错误: 请使用 sudo 运行此命令${NC}"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# 获取安装目录
|
||||
get_install_dir() {
|
||||
if [ -n "$1" ]; then
|
||||
INSTALL_DIR="$1"
|
||||
fi
|
||||
PID_FILE="$INSTALL_DIR/$APP_NAME.pid"
|
||||
}
|
||||
|
||||
# 环境检查
|
||||
cmd_check() {
|
||||
echo "========== 3588AdminBackend 环境检查 =========="
|
||||
echo ""
|
||||
|
||||
PASS=0
|
||||
FAIL=0
|
||||
WARN=0
|
||||
|
||||
check_pass() {
|
||||
echo -e "${GREEN}✓${NC} $1"
|
||||
((PASS++))
|
||||
}
|
||||
|
||||
check_fail() {
|
||||
echo -e "${RED}✗${NC} $1"
|
||||
((FAIL++))
|
||||
}
|
||||
|
||||
check_warn() {
|
||||
echo -e "${YELLOW}⚠${NC} $1"
|
||||
((WARN++))
|
||||
}
|
||||
|
||||
# 1. 检查操作系统
|
||||
echo "[系统信息]"
|
||||
echo " 主机名: $(hostname)"
|
||||
if [ -f /etc/os-release ]; then
|
||||
. /etc/os-release
|
||||
echo " 操作系统: $NAME $VERSION"
|
||||
if [[ "$NAME" == *"Ubuntu"* ]] && [[ "$VERSION_ID" == "22.04" ]]; then
|
||||
check_pass "Ubuntu 22.04 detected"
|
||||
else
|
||||
check_warn "非 Ubuntu 22.04,可能兼容但未经测试"
|
||||
fi
|
||||
else
|
||||
check_warn "无法检测操作系统版本"
|
||||
fi
|
||||
|
||||
# 2. 检查架构
|
||||
echo ""
|
||||
echo "[硬件信息]"
|
||||
ARCH=$(uname -m)
|
||||
echo " 架构: $ARCH"
|
||||
if [ "$ARCH" = "x86_64" ]; then
|
||||
check_pass "x86_64 架构"
|
||||
elif [ "$ARCH" = "aarch64" ]; then
|
||||
check_warn "ARM64 架构,请使用 ARM64 版本二进制"
|
||||
else
|
||||
check_warn "未知架构: $ARCH"
|
||||
fi
|
||||
|
||||
echo " CPU: $(nproc) 核"
|
||||
echo " 内存: $(free -h | awk '/^Mem:/ {print $2}')"
|
||||
|
||||
# 3. 检查网络工具
|
||||
echo ""
|
||||
echo "[网络工具]"
|
||||
if command -v curl >/dev/null 2>&1; then
|
||||
check_pass "curl 已安装"
|
||||
else
|
||||
check_warn "curl 未安装"
|
||||
fi
|
||||
|
||||
if command -v netstat >/dev/null 2>&1 || command -v ss >/dev/null 2>&1; then
|
||||
check_pass "网络工具(netstat/ss)已安装"
|
||||
else
|
||||
check_warn "建议安装 net-tools 或 iproute2"
|
||||
fi
|
||||
|
||||
# 4. 检查端口占用
|
||||
echo ""
|
||||
echo "[端口检查]"
|
||||
PORT_18080=false
|
||||
PORT_35688=false
|
||||
|
||||
if command -v ss >/dev/null 2>&1; then
|
||||
PORT_18080=$(ss -tln 2>/dev/null | grep -q ':18080 ' && echo true || echo false)
|
||||
PORT_35688=$(ss -uln 2>/dev/null | grep -q ':35688 ' && echo true || echo false)
|
||||
elif command -v netstat >/dev/null 2>&1; then
|
||||
PORT_18080=$(netstat -tln 2>/dev/null | grep -q ':18080 ' && echo true || echo false)
|
||||
PORT_35688=$(netstat -uln 2>/dev/null | grep -q ':35688 ' && echo true || echo false)
|
||||
fi
|
||||
|
||||
if [ "$PORT_18080" = true ]; then
|
||||
check_warn "端口 18080 已被占用"
|
||||
else
|
||||
check_pass "端口 18080 可用"
|
||||
fi
|
||||
|
||||
if [ "$PORT_35688" = true ]; then
|
||||
check_warn "端口 35688 已被占用"
|
||||
else
|
||||
check_pass "端口 35688 可用"
|
||||
fi
|
||||
|
||||
# 5. 检查防火墙
|
||||
echo ""
|
||||
echo "[防火墙]"
|
||||
if command -v ufw >/dev/null 2>&1; then
|
||||
UFW_STATUS=$(ufw status 2>/dev/null | grep -i status | awk '{print $2}')
|
||||
echo " UFW 状态: $UFW_STATUS"
|
||||
elif command -v firewall-cmd >/dev/null 2>&1; then
|
||||
check_warn "检测到 firewalld,请手动配置端口"
|
||||
else
|
||||
echo " 未检测到防火墙"
|
||||
fi
|
||||
|
||||
# 6. 检查磁盘空间
|
||||
echo ""
|
||||
echo "[磁盘空间]"
|
||||
DISK_AVAIL=$(df -BG /opt 2>/dev/null | tail -1 | awk '{print $4}' | tr -d 'G')
|
||||
if [ -z "$DISK_AVAIL" ]; then
|
||||
DISK_AVAIL=$(df -BG / 2>/dev/null | tail -1 | awk '{print $4}' | tr -d 'G')
|
||||
fi
|
||||
|
||||
if [ -n "$DISK_AVAIL" ] && [ "$DISK_AVAIL" -ge 1 ]; then
|
||||
check_pass "磁盘空间充足 (${DISK_AVAIL}G 可用)"
|
||||
else
|
||||
check_warn "磁盘空间不足 (${DISK_AVAIL:-0}G 可用,建议至少 1GB)"
|
||||
fi
|
||||
|
||||
# 7. 检查权限
|
||||
echo ""
|
||||
echo "[权限检查]"
|
||||
if [ "$EUID" -eq 0 ]; then
|
||||
check_pass "当前为 root 用户"
|
||||
else
|
||||
check_warn "当前非 root 用户,安装需要 root 权限"
|
||||
fi
|
||||
|
||||
# 8. 检查 Python
|
||||
echo ""
|
||||
echo "[其他工具]"
|
||||
if command -v python3 >/dev/null 2>&1; then
|
||||
check_pass "Python3 已安装 ($(python3 --version))"
|
||||
else
|
||||
check_warn "Python3 未安装 (用于配置验证)"
|
||||
fi
|
||||
|
||||
# 总结
|
||||
echo ""
|
||||
echo "========== 检查总结 =========="
|
||||
echo -e "通过: ${GREEN}$PASS${NC} 警告: ${YELLOW}$WARN${NC} 失败: ${RED}$FAIL${NC}"
|
||||
echo ""
|
||||
|
||||
if [ $FAIL -gt 0 ]; then
|
||||
echo -e "${RED}环境检查未通过,请解决上述问题后再安装${NC}"
|
||||
exit 1
|
||||
elif [ $WARN -gt 0 ]; then
|
||||
echo -e "${YELLOW}环境基本满足,但有一些警告需要注意${NC}"
|
||||
return 0
|
||||
else
|
||||
echo -e "${GREEN}环境检查全部通过,可以安装${NC}"
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
# 安装
|
||||
cmd_install() {
|
||||
check_root
|
||||
get_install_dir "$1"
|
||||
|
||||
local CURRENT_DIR="$SCRIPT_DIR"
|
||||
local BASE_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
|
||||
echo "========== 3588AdminBackend 离线安装 =========="
|
||||
echo "安装目录: $INSTALL_DIR"
|
||||
echo ""
|
||||
|
||||
# 检查安装目录
|
||||
if [ -d "$INSTALL_DIR" ] && [ "$(ls -A $INSTALL_DIR 2>/dev/null)" ]; then
|
||||
echo -e "${YELLOW}警告: 安装目录 $INSTALL_DIR 已存在且不为空${NC}"
|
||||
read -p "是否覆盖? (y/N): " -n 1 -r
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
echo "安装已取消"
|
||||
exit 1
|
||||
fi
|
||||
# 备份现有配置
|
||||
if [ -f "$INSTALL_DIR/config/managerd.json" ]; then
|
||||
local BACKUP_FILE="$INSTALL_DIR/config/managerd.json.bak.$(date +%Y%m%d%H%M%S)"
|
||||
echo "备份现有配置到: $BACKUP_FILE"
|
||||
cp "$INSTALL_DIR/config/managerd.json" "$BACKUP_FILE"
|
||||
fi
|
||||
fi
|
||||
|
||||
# 1. 安装依赖包
|
||||
if [ -d "$BASE_DIR/deps" ] && [ "$(ls -A $BASE_DIR/deps/*.deb 2>/dev/null)" ]; then
|
||||
echo "[1/5] 安装依赖包..."
|
||||
cd "$BASE_DIR/deps"
|
||||
for pkg in *.deb; do
|
||||
echo " 安装: $pkg"
|
||||
dpkg -i "$pkg" 2>/dev/null || true
|
||||
done
|
||||
apt-get install -f -y 2>/dev/null || true
|
||||
else
|
||||
echo "[1/5] 跳过依赖包安装 (无依赖包)"
|
||||
fi
|
||||
|
||||
# 2. 创建安装目录
|
||||
echo "[2/5] 创建安装目录..."
|
||||
mkdir -p "$INSTALL_DIR"
|
||||
|
||||
echo " 复制二进制文件..."
|
||||
mkdir -p "$INSTALL_DIR/bin"
|
||||
cp "$BASE_DIR/bin/managerd" "$INSTALL_DIR/bin/" 2>/dev/null || {
|
||||
echo -e "${RED}错误: 未找到 managerd 二进制文件${NC}"
|
||||
echo "请确保在打包前已编译"
|
||||
exit 1
|
||||
}
|
||||
|
||||
echo " 复制配置文件..."
|
||||
mkdir -p "$INSTALL_DIR/config"
|
||||
if [ -f "$BASE_DIR/config/managerd.json" ]; then
|
||||
cp "$BASE_DIR/config/managerd.json" "$INSTALL_DIR/config/"
|
||||
elif [ -f "$BASE_DIR/config/managerd.json.example" ]; then
|
||||
cp "$BASE_DIR/config/managerd.json.example" "$INSTALL_DIR/config/"
|
||||
fi
|
||||
|
||||
# 复制模板文件
|
||||
if [ -d "$BASE_DIR/templates" ]; then
|
||||
echo " 复制模板文件..."
|
||||
cp -r "$BASE_DIR/templates" "$INSTALL_DIR/"
|
||||
fi
|
||||
|
||||
# 3. 设置权限
|
||||
echo "[3/5] 设置权限..."
|
||||
chmod +x "$INSTALL_DIR/bin/managerd"
|
||||
mkdir -p "$INSTALL_DIR/logs" || {
|
||||
echo -e "${RED}错误: 无法创建日志目录 $INSTALL_DIR/logs${NC}"
|
||||
exit 1
|
||||
}
|
||||
chmod 755 "$INSTALL_DIR/logs" || {
|
||||
echo -e "${RED}错误: 无法设置日志目录权限${NC}"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# 4. 初始化配置文件
|
||||
echo "[4/5] 初始化配置文件..."
|
||||
if [ ! -f "$INSTALL_DIR/config/managerd.json" ]; then
|
||||
cat > "$INSTALL_DIR/config/managerd.json" << 'EOF'
|
||||
{
|
||||
"listen": "0.0.0.0:18080",
|
||||
"discovery_port": 35688,
|
||||
"discovery_timeout_ms": 1200,
|
||||
"offline_after_ms": 10000,
|
||||
"agent_token": "CHANGE_ME",
|
||||
"concurrency": 5
|
||||
}
|
||||
EOF
|
||||
echo -e " ${GREEN}已创建默认配置文件${NC}"
|
||||
echo -e " ${YELLOW}⚠️ 请编辑 $INSTALL_DIR/config/managerd.json 修改配置(特别是 agent_token)${NC}"
|
||||
else
|
||||
echo " 配置文件已存在,保留现有配置"
|
||||
fi
|
||||
|
||||
# 5. 复制管理脚本
|
||||
echo "[5/5] 安装管理脚本..."
|
||||
mkdir -p "$INSTALL_DIR/scripts"
|
||||
cp "$CURRENT_DIR/3588admin" "$INSTALL_DIR/scripts/"
|
||||
chmod +x "$INSTALL_DIR/scripts/3588admin"
|
||||
|
||||
# 创建快捷方式
|
||||
ln -sf "$INSTALL_DIR/scripts/3588admin" /usr/local/bin/3588admin-start 2>/dev/null || true
|
||||
ln -sf "$INSTALL_DIR/scripts/3588admin" /usr/local/bin/3588admin-stop 2>/dev/null || true
|
||||
ln -sf "$INSTALL_DIR/scripts/3588admin" /usr/local/bin/3588admin-status 2>/dev/null || true
|
||||
ln -sf "$INSTALL_DIR/scripts/3588admin" /usr/local/bin/3588admin 2>/dev/null || true
|
||||
|
||||
# 安装 Systemd 服务
|
||||
if [ -f "$CURRENT_DIR/3588admin.service" ]; then
|
||||
echo "[可选] 安装 Systemd 服务..."
|
||||
cp "$CURRENT_DIR/3588admin.service" /etc/systemd/system/
|
||||
sed -i "s|/opt/3588admin|$INSTALL_DIR|g" /etc/systemd/system/3588admin.service
|
||||
systemctl daemon-reload
|
||||
echo " 已安装 Systemd 服务"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo -e "${GREEN}========== 安装完成 ==========${NC}"
|
||||
echo "安装目录: $INSTALL_DIR"
|
||||
echo ""
|
||||
echo "使用命令:"
|
||||
echo " 3588admin start - 启动服务"
|
||||
echo " 3588admin stop - 停止服务"
|
||||
echo " 3588admin status - 查看状态"
|
||||
echo " 3588admin restart - 重启服务"
|
||||
echo " 3588admin upgrade - 升级服务"
|
||||
echo " 3588admin uninstall - 卸载服务"
|
||||
echo ""
|
||||
echo -e "${YELLOW}重要提示:${NC}"
|
||||
echo " 1. 请先编辑配置文件: $INSTALL_DIR/config/managerd.json"
|
||||
echo " 2. 务必修改 agent_token 为安全的随机字符串"
|
||||
echo ""
|
||||
echo -e "${YELLOW}防火墙配置:${NC}"
|
||||
echo " 默认监听 0.0.0.0:18080,如需外部访问,请开放防火墙端口:"
|
||||
echo " sudo ufw allow 18080/tcp # HTTP API 端口"
|
||||
echo " sudo ufw allow 35688/udp # UDP 设备发现端口"
|
||||
echo " sudo ufw reload"
|
||||
}
|
||||
|
||||
# 启动服务
|
||||
cmd_start() {
|
||||
get_install_dir "$1"
|
||||
|
||||
local BIN_PATH="$INSTALL_DIR/bin/$APP_NAME"
|
||||
local CONFIG_PATH="$INSTALL_DIR/config/managerd.json"
|
||||
local LOG_DIR="$INSTALL_DIR/logs"
|
||||
|
||||
echo "========== 启动 3588AdminBackend =========="
|
||||
echo "应用目录: $INSTALL_DIR"
|
||||
echo "配置文件: $CONFIG_PATH"
|
||||
echo ""
|
||||
|
||||
# 检查二进制文件
|
||||
if [ ! -f "$BIN_PATH" ]; then
|
||||
echo -e "${RED}错误: 未找到二进制文件: $BIN_PATH${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 检查配置文件
|
||||
if [ ! -f "$CONFIG_PATH" ]; then
|
||||
echo -e "${RED}错误: 配置文件不存在: $CONFIG_PATH${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 验证 JSON 格式
|
||||
if command -v python3 &> /dev/null; then
|
||||
if ! python3 -m json.tool "$CONFIG_PATH" > /dev/null 2>&1; then
|
||||
echo -e "${RED}错误: 配置文件 JSON 格式不正确${NC}"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# 创建日志目录
|
||||
if [ ! -d "$LOG_DIR" ]; then
|
||||
mkdir -p "$LOG_DIR" 2>/dev/null || {
|
||||
echo -e "${RED}错误: 无法创建日志目录: $LOG_DIR${NC}"
|
||||
echo "请检查权限或手动创建: sudo mkdir -p $LOG_DIR"
|
||||
exit 1
|
||||
}
|
||||
fi
|
||||
|
||||
# 检查日志目录是否可写
|
||||
if [ ! -w "$LOG_DIR" ]; then
|
||||
echo -e "${RED}错误: 日志目录不可写: $LOG_DIR${NC}"
|
||||
echo "请修复权限: sudo chmod 755 $LOG_DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 检查是否已在运行
|
||||
if [ -f "$PID_FILE" ]; then
|
||||
local PID=$(cat "$PID_FILE")
|
||||
if ps -p "$PID" > /dev/null 2>&1; then
|
||||
echo -e "${YELLOW}警告: $APP_NAME 已在运行 (PID: $PID)${NC}"
|
||||
exit 1
|
||||
else
|
||||
rm -f "$PID_FILE"
|
||||
fi
|
||||
fi
|
||||
|
||||
# 启动服务
|
||||
echo "正在启动 $APP_NAME..."
|
||||
nohup "$BIN_PATH" "$CONFIG_PATH" >> "$LOG_DIR/$APP_NAME.log" 2>&1 &
|
||||
local PID=$!
|
||||
echo $PID > "$PID_FILE"
|
||||
|
||||
# 等待启动
|
||||
sleep 2
|
||||
if ps -p "$PID" > /dev/null 2>&1; then
|
||||
echo ""
|
||||
echo -e "${GREEN}✅ 启动成功!${NC}"
|
||||
echo " PID: $PID"
|
||||
echo " 日志: $LOG_DIR/$APP_NAME.log"
|
||||
echo ""
|
||||
echo "查看日志: tail -f $LOG_DIR/$APP_NAME.log"
|
||||
else
|
||||
echo ""
|
||||
echo -e "${RED}❌ 启动失败${NC}"
|
||||
echo ""
|
||||
echo "可能的错误原因:"
|
||||
echo " 1. 端口 18080 被占用"
|
||||
echo " 2. 配置文件格式错误"
|
||||
echo " 3. 权限不足"
|
||||
echo ""
|
||||
echo "尝试直接运行查看详细错误:"
|
||||
echo " sudo $BIN_PATH $CONFIG_PATH"
|
||||
echo ""
|
||||
echo "或检查日志:"
|
||||
if [ -f "$LOG_DIR/$APP_NAME.log" ]; then
|
||||
echo " tail -20 $LOG_DIR/$APP_NAME.log"
|
||||
fi
|
||||
rm -f "$PID_FILE"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# 停止服务
|
||||
cmd_stop() {
|
||||
get_install_dir "$1"
|
||||
|
||||
echo "========== 停止 3588AdminBackend =========="
|
||||
|
||||
if [ -f "$PID_FILE" ]; then
|
||||
local PID=$(cat "$PID_FILE")
|
||||
if ps -p "$PID" > /dev/null 2>&1; then
|
||||
echo "正在停止 $APP_NAME (PID: $PID)..."
|
||||
kill "$PID"
|
||||
|
||||
echo -n "等待进程结束"
|
||||
for i in {1..10}; do
|
||||
if ! ps -p "$PID" > /dev/null 2>&1; then
|
||||
echo ""
|
||||
echo -e "${GREEN}✅ 已停止${NC}"
|
||||
rm -f "$PID_FILE"
|
||||
return 0
|
||||
fi
|
||||
echo -n "."
|
||||
sleep 1
|
||||
done
|
||||
echo ""
|
||||
|
||||
echo "强制结束进程..."
|
||||
kill -9 "$PID" 2>/dev/null || true
|
||||
rm -f "$PID_FILE"
|
||||
echo -e "${GREEN}✅ 已强制停止${NC}"
|
||||
else
|
||||
echo -e "${YELLOW}ℹ️ 进程不存在 (PID: $PID)${NC}"
|
||||
rm -f "$PID_FILE"
|
||||
fi
|
||||
else
|
||||
# 尝试查找进程
|
||||
local PID=$(pgrep -f "^$INSTALL_DIR/bin/$APP_NAME" | head -1)
|
||||
if [ -n "$PID" ]; then
|
||||
echo "发现运行中的进程 (PID: $PID),尝试停止..."
|
||||
kill "$PID" 2>/dev/null || true
|
||||
sleep 2
|
||||
if ! ps -p "$PID" > /dev/null 2>&1; then
|
||||
echo -e "${GREEN}✅ 已停止${NC}"
|
||||
else
|
||||
kill -9 "$PID" 2>/dev/null || true
|
||||
echo -e "${GREEN}✅ 已强制停止${NC}"
|
||||
fi
|
||||
else
|
||||
echo -e "${YELLOW}ℹ️ $APP_NAME 未在运行${NC}"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# 重启服务
|
||||
cmd_restart() {
|
||||
cmd_stop "$@"
|
||||
sleep 1
|
||||
cmd_start "$@"
|
||||
}
|
||||
|
||||
# 查看状态
|
||||
cmd_status() {
|
||||
get_install_dir "$1"
|
||||
|
||||
local BIN_PATH="$INSTALL_DIR/bin/$APP_NAME"
|
||||
local CONFIG_PATH="$INSTALL_DIR/config/managerd.json"
|
||||
local LOG_DIR="$INSTALL_DIR/logs"
|
||||
|
||||
echo "========== 3588AdminBackend 状态 =========="
|
||||
echo ""
|
||||
echo "基本信息:"
|
||||
echo " 应用目录: $INSTALL_DIR"
|
||||
echo " 二进制文件: $BIN_PATH"
|
||||
echo " 配置文件: $CONFIG_PATH"
|
||||
echo " 日志目录: $LOG_DIR"
|
||||
|
||||
# 检查二进制文件
|
||||
if [ -f "$BIN_PATH" ]; then
|
||||
echo -e " 二进制状态: ${GREEN}✅ 存在${NC}"
|
||||
else
|
||||
echo -e " 二进制状态: ${RED}❌ 不存在${NC}"
|
||||
fi
|
||||
|
||||
# 检查配置文件
|
||||
if [ -f "$CONFIG_PATH" ]; then
|
||||
echo -e " 配置文件: ${GREEN}✅ 存在${NC}"
|
||||
if command -v python3 &> /dev/null; then
|
||||
local LISTEN=$(python3 -c "import json; print(json.load(open('$CONFIG_PATH')).get('listen', 'N/A'))" 2>/dev/null)
|
||||
local DISCOVERY_PORT=$(python3 -c "import json; print(json.load(open('$CONFIG_PATH')).get('discovery_port', 'N/A'))" 2>/dev/null)
|
||||
echo " 监听地址: $LISTEN"
|
||||
echo " 发现端口: $DISCOVERY_PORT (UDP)"
|
||||
fi
|
||||
else
|
||||
echo -e " 配置文件: ${RED}❌ 不存在${NC}"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "运行状态:"
|
||||
|
||||
# 检查进程
|
||||
if [ -f "$PID_FILE" ]; then
|
||||
local PID=$(cat "$PID_FILE")
|
||||
if ps -p "$PID" > /dev/null 2>&1; then
|
||||
echo -e " 进程状态: ${GREEN}🟢 运行中${NC}"
|
||||
echo " PID: $PID"
|
||||
|
||||
if command -v ps &> /dev/null; then
|
||||
echo ""
|
||||
echo "进程详情:"
|
||||
ps -p "$PID" -o pid,pcpu,pmem,cmd --no-headers 2>/dev/null | while read line; do
|
||||
echo " $line"
|
||||
done
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "网络监听:"
|
||||
if command -v ss &> /dev/null; then
|
||||
ss -tlnp 2>/dev/null | grep "$PID" | head -3 | while read line; do
|
||||
echo " $line"
|
||||
done
|
||||
elif command -v netstat &> /dev/null; then
|
||||
netstat -tlnp 2>/dev/null | grep "$PID/" | head -3 | while read line; do
|
||||
echo " $line"
|
||||
done
|
||||
fi
|
||||
|
||||
# API 测试
|
||||
if command -v curl &> /dev/null; then
|
||||
echo ""
|
||||
echo "API 测试:"
|
||||
local HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" "http://127.0.0.1:18080/api/devices" 2>/dev/null || echo "000")
|
||||
if [ "$HTTP_CODE" = "200" ] || [ "$HTTP_CODE" = "401" ]; then
|
||||
echo -e " ${GREEN}✅ HTTP API 响应正常 (HTTP $HTTP_CODE)${NC}"
|
||||
elif [ "$HTTP_CODE" = "000" ]; then
|
||||
echo -e " ${YELLOW}⚠️ 无法连接 HTTP API${NC}"
|
||||
else
|
||||
echo " ℹ️ HTTP API 响应: $HTTP_CODE"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
echo -e " 进程状态: ${RED}🔴 未运行 (PID 文件存在但进程不存在)${NC}"
|
||||
fi
|
||||
else
|
||||
local PID=$(pgrep -f "^$BIN_PATH" | head -1)
|
||||
if [ -n "$PID" ]; then
|
||||
echo -e " 进程状态: ${YELLOW}🟡 运行中 (无 PID 文件,PID: $PID)${NC}"
|
||||
else
|
||||
echo -e " 进程状态: ${BLUE}⚫ 未运行${NC}"
|
||||
fi
|
||||
fi
|
||||
|
||||
# 日志信息
|
||||
echo ""
|
||||
echo "日志信息:"
|
||||
if [ -d "$LOG_DIR" ]; then
|
||||
local NEWEST_LOG=$(ls -t "$LOG_DIR"/*.log 2>/dev/null | head -1)
|
||||
if [ -n "$NEWEST_LOG" ]; then
|
||||
echo " 最新日志 ($NEWEST_LOG):"
|
||||
tail -n 3 "$NEWEST_LOG" | while read line; do
|
||||
echo " $line"
|
||||
done
|
||||
else
|
||||
echo " 无日志文件"
|
||||
fi
|
||||
else
|
||||
echo " 日志目录不存在"
|
||||
fi
|
||||
}
|
||||
|
||||
# 升级服务
|
||||
cmd_upgrade() {
|
||||
check_root
|
||||
get_install_dir "$1"
|
||||
|
||||
local SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
local BACKUP_DIR="/root/3588admin-backup-$(date +%Y%m%d%H%M%S)"
|
||||
|
||||
echo "========== 3588AdminBackend 升级 =========="
|
||||
echo "安装目录: $INSTALL_DIR"
|
||||
echo "备份目录: $BACKUP_DIR"
|
||||
echo ""
|
||||
|
||||
# 检查安装目录是否存在
|
||||
if [ ! -d "$INSTALL_DIR" ]; then
|
||||
echo -e "${RED}错误: 安装目录不存在: $INSTALL_DIR${NC}"
|
||||
echo "请先运行安装命令"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 确认
|
||||
read -p "确定要升级 3588AdminBackend? (y/N): " -n 1 -r
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
echo "升级已取消"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# 1. 停止服务
|
||||
echo "[1/5] 停止服务..."
|
||||
cmd_stop "$@" 2>/dev/null || true
|
||||
sleep 2
|
||||
|
||||
# 2. 备份
|
||||
echo "[2/5] 备份现有数据..."
|
||||
mkdir -p "$BACKUP_DIR"
|
||||
|
||||
if [ -f "$INSTALL_DIR/config/managerd.json" ]; then
|
||||
cp "$INSTALL_DIR/config/managerd.json" "$BACKUP_DIR/"
|
||||
echo " 已备份配置文件"
|
||||
fi
|
||||
|
||||
if [ -d "$INSTALL_DIR/logs" ]; then
|
||||
cp -r "$INSTALL_DIR/logs" "$BACKUP_DIR/"
|
||||
echo " 已备份日志文件"
|
||||
fi
|
||||
|
||||
if [ -f "$INSTALL_DIR/bin/managerd" ]; then
|
||||
cp "$INSTALL_DIR/bin/managerd" "$BACKUP_DIR/managerd.old"
|
||||
echo " 已备份旧版本二进制"
|
||||
fi
|
||||
|
||||
# 3. 更新二进制文件
|
||||
echo "[3/5] 更新二进制文件..."
|
||||
local BASE_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
if [ -f "$BASE_DIR/bin/managerd" ]; then
|
||||
cp "$BASE_DIR/bin/managerd" "$INSTALL_DIR/bin/managerd"
|
||||
chmod +x "$INSTALL_DIR/bin/managerd"
|
||||
echo -e " ${GREEN}已更新二进制文件${NC}"
|
||||
else
|
||||
echo -e "${YELLOW}警告: 未找到新的二进制文件${NC}"
|
||||
fi
|
||||
|
||||
# 4. 更新脚本
|
||||
echo "[4/5] 更新脚本..."
|
||||
cp "$SCRIPT_DIR/3588admin" "$INSTALL_DIR/scripts/"
|
||||
chmod +x "$INSTALL_DIR/scripts/3588admin"
|
||||
echo " 已更新管理脚本"
|
||||
|
||||
# 5. 启动服务
|
||||
echo "[5/5] 启动服务..."
|
||||
cmd_start "$@"
|
||||
|
||||
echo ""
|
||||
echo -e "${GREEN}========== 升级完成 ==========${NC}"
|
||||
echo "备份位置: $BACKUP_DIR"
|
||||
}
|
||||
|
||||
# 卸载服务
|
||||
cmd_uninstall() {
|
||||
check_root
|
||||
get_install_dir "$1"
|
||||
|
||||
echo "========== 3588AdminBackend 卸载 =========="
|
||||
echo "安装目录: $INSTALL_DIR"
|
||||
echo ""
|
||||
|
||||
# 确认
|
||||
read -p "确定要完全卸载 3588AdminBackend? 此操作不可恢复! (y/N): " -n 1 -r
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
echo "卸载已取消"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# 1. 停止服务
|
||||
echo "[1/4] 停止服务..."
|
||||
cmd_stop "$@" 2>/dev/null || true
|
||||
|
||||
# 停止 systemd 服务
|
||||
if systemctl is-active --quiet 3588admin 2>/dev/null; then
|
||||
systemctl stop 3588admin
|
||||
fi
|
||||
if systemctl is-enabled --quiet 3588admin 2>/dev/null; then
|
||||
systemctl disable 3588admin
|
||||
fi
|
||||
|
||||
# 2. 删除 systemd 服务文件
|
||||
echo "[2/4] 删除 Systemd 服务..."
|
||||
if [ -f "/etc/systemd/system/3588admin.service" ]; then
|
||||
rm -f "/etc/systemd/system/3588admin.service"
|
||||
systemctl daemon-reload
|
||||
echo " 已删除 systemd 服务"
|
||||
fi
|
||||
|
||||
# 3. 删除快捷方式
|
||||
echo "[3/4] 删除快捷方式..."
|
||||
rm -f /usr/local/bin/3588admin-start
|
||||
rm -f /usr/local/bin/3588admin-stop
|
||||
rm -f /usr/local/bin/3588admin-status
|
||||
rm -f /usr/local/bin/3588admin
|
||||
echo " 已删除命令快捷方式"
|
||||
|
||||
# 4. 备份并删除安装目录
|
||||
echo "[4/4] 删除安装文件..."
|
||||
local BACKUP_DIR=""
|
||||
if [ -d "$INSTALL_DIR" ]; then
|
||||
if [ -f "$INSTALL_DIR/config/managerd.json" ]; then
|
||||
BACKUP_DIR="/root/3588admin-backup-$(date +%Y%m%d%H%M%S)"
|
||||
mkdir -p "$BACKUP_DIR"
|
||||
cp "$INSTALL_DIR/config/managerd.json" "$BACKUP_DIR/"
|
||||
echo " 配置已备份到: $BACKUP_DIR/"
|
||||
fi
|
||||
|
||||
rm -rf "$INSTALL_DIR"
|
||||
echo " 已删除安装目录: $INSTALL_DIR"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo -e "${GREEN}========== 卸载完成 ==========${NC}"
|
||||
if [ -n "$BACKUP_DIR" ]; then
|
||||
echo "配置文件备份: $BACKUP_DIR/managerd.json"
|
||||
fi
|
||||
}
|
||||
|
||||
# 主函数
|
||||
main() {
|
||||
# 如果没有参数,显示帮助
|
||||
if [ $# -eq 0 ]; then
|
||||
cmd_help
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# 解析命令
|
||||
COMMAND="$1"
|
||||
shift
|
||||
|
||||
case "$COMMAND" in
|
||||
install)
|
||||
cmd_install "$@"
|
||||
;;
|
||||
status)
|
||||
cmd_status "$@"
|
||||
;;
|
||||
start)
|
||||
cmd_start "$@"
|
||||
;;
|
||||
stop)
|
||||
cmd_stop "$@"
|
||||
;;
|
||||
restart)
|
||||
cmd_restart "$@"
|
||||
;;
|
||||
upgrade)
|
||||
cmd_upgrade "$@"
|
||||
;;
|
||||
uninstall)
|
||||
cmd_uninstall "$@"
|
||||
;;
|
||||
check)
|
||||
cmd_check "$@"
|
||||
;;
|
||||
help|--help|-h)
|
||||
cmd_help
|
||||
;;
|
||||
*)
|
||||
# 兼容快捷方式调用
|
||||
# 如果是通过快捷方式调用,脚本名就是命令
|
||||
SCRIPT_NAME=$(basename "$0")
|
||||
case "$SCRIPT_NAME" in
|
||||
3588admin-start)
|
||||
cmd_start "$@"
|
||||
;;
|
||||
3588admin-stop)
|
||||
cmd_stop "$@"
|
||||
;;
|
||||
3588admin-status)
|
||||
cmd_status "$@"
|
||||
;;
|
||||
*)
|
||||
echo -e "${RED}错误: 未知命令 '$COMMAND'${NC}"
|
||||
echo ""
|
||||
cmd_help
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
main "$@"
|
||||
@ -1,31 +0,0 @@
|
||||
[Unit]
|
||||
Description=3588AdminBackend Service
|
||||
Documentation=https://github.com/your-org/3588AdminBackend
|
||||
After=network.target network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=root
|
||||
Group=root
|
||||
WorkingDirectory=/opt/3588admin
|
||||
ExecStart=/opt/3588admin/bin/managerd /opt/3588admin/config/managerd.json
|
||||
ExecReload=/bin/kill -HUP $MAINPID
|
||||
KillMode=process
|
||||
KillSignal=SIGTERM
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
StartLimitInterval=60s
|
||||
StartLimitBurst=3
|
||||
|
||||
# 资源限制(根据需要调整)
|
||||
# LimitNOFILE=65535
|
||||
# LimitNPROC=4096
|
||||
|
||||
# 安全设置
|
||||
NoNewPrivileges=false
|
||||
ProtectSystem=false
|
||||
ProtectHome=false
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@ -1,16 +0,0 @@
|
||||
{
|
||||
"name": "test-template",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"fps": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"body": {
|
||||
"global": {
|
||||
"fps": "{{fps}}"
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user