From cda9702548045381344d96204b6ee34e643f3476 Mon Sep 17 00:00:00 2001 From: tian <11429339@qq.com> Date: Wed, 25 Feb 2026 11:00:55 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E9=83=A8=E7=BD=B2=E8=84=9A?= =?UTF-8?q?=E6=9C=AC=E5=92=8C=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- PRD_04_Manager_ConfigGUI_AgentAPI.md | 45 +- Readme.md | 39 ++ docs/离线部署文档.md | 854 ++++++++++++++++++++++++ plan.md | 6 + scripts/deploy/3588admin.service | 31 + scripts/deploy/Manual.md | 516 ++++++++++++++ scripts/deploy/build-offline-package.sh | 207 ++++++ scripts/deploy/check-env.sh | 191 ++++++ scripts/deploy/install.sh | 158 +++++ scripts/deploy/start.sh | 98 +++ scripts/deploy/status.sh | 154 +++++ scripts/deploy/stop.sh | 69 ++ scripts/deploy/uninstall.sh | 79 +++ scripts/deploy/upgrade.sh | 104 +++ scripts/dev-run.sh | 56 ++ 15 files changed, 2606 insertions(+), 1 deletion(-) create mode 100644 docs/离线部署文档.md create mode 100644 scripts/deploy/3588admin.service create mode 100644 scripts/deploy/Manual.md create mode 100644 scripts/deploy/build-offline-package.sh create mode 100644 scripts/deploy/check-env.sh create mode 100644 scripts/deploy/install.sh create mode 100644 scripts/deploy/start.sh create mode 100644 scripts/deploy/status.sh create mode 100644 scripts/deploy/stop.sh create mode 100644 scripts/deploy/uninstall.sh create mode 100644 scripts/deploy/upgrade.sh create mode 100644 scripts/dev-run.sh diff --git a/PRD_04_Manager_ConfigGUI_AgentAPI.md b/PRD_04_Manager_ConfigGUI_AgentAPI.md index ffc40ca..5ba9795 100644 --- a/PRD_04_Manager_ConfigGUI_AgentAPI.md +++ b/PRD_04_Manager_ConfigGUI_AgentAPI.md @@ -3,6 +3,7 @@ > 适用版本:V1(2026-01) > > 范围:**仅控制端 GUI/managerd 如何调用设备端 rk3588-agent**。 +> > - 本项目中已在 `agent + media-server` 实现本文档所需能力。 > - **不包含**配置程序(前端/后端)具体 UI 代码实现细节。 @@ -36,15 +37,18 @@ ## 3. 鉴权与错误处理 ### 3.1 鉴权 + - Header:`X-RK-Token: ` - 写接口(会写盘/改状态)必须鉴权。 - 读接口默认可不鉴权;若设备端配置 `agent.require_token_for_read=true`,则读接口也必须鉴权。 ### 3.2 统一错误返回 + - 成功:`2xx`,一般为 `{"ok":true,...}` 或业务 JSON - 失败:`4xx/5xx`,返回 `{"error":"..."}` 常见 HTTP: + - `401`:unauthorized - `400`:validation failed / invalid json - `404`:not found @@ -56,6 +60,7 @@ ## 4. GUI 页面与调用流程 ### 4.1 设备详情页(只读) + 1) 设备信息:`GET /v1/info` 2) 运行态通道摘要:`GET /v1/graphs` 3) 单通道详情(可选):`GET /v1/graphs/{name}` @@ -64,16 +69,20 @@ ### 4.2 通道配置页(核心:instances) #### 4.2.1 初始化 + 1) 获取 schema(渲染表单):`GET /v1/config/ui/schema` 2) 获取当前 state(回显):`GET /v1/config/ui/state` GUI 侧以 `instances[]` 为“通道列表”。 #### 4.2.2 校验/预览(dry-run) + 用户编辑完成后: + - `POST /v1/config/ui/plan` 返回: + - `generated_config`:生成出来的 root config(可用于预览/导出) - `diff`:added/removed/changed(实例级别) @@ -81,15 +90,18 @@ GUI 侧以 `instances[]` 为“通道列表”。 > 真正的构图/插件/模型加载等校验发生在 apply → media-server reload 阶段。 #### 4.2.3 应用配置 + - `POST /v1/config/ui/apply` 行为: + 1) agent 生成新的 root config(只包含 `global/queue/templates/instances`) 2) 写盘到 `agent.config_path` 3) 调用 media-server reload 4) reload 失败则自动 rollback 并返回 500 #### 4.2.4 回滚(手动) + - `POST /v1/media-server/rollback` > 回滚语义:回滚到“上一次成功的**源配置**”(保留 templates/instances,不会被 expanded 覆盖),便于 GUI 二次编辑。 @@ -97,6 +109,7 @@ GUI 侧以 `instances[]` 为“通道列表”。 ### 4.3 人脸库管理页 #### 4.3.1 上传人脸库 + - `PUT /v1/face-gallery` - Content-Type:`application/octet-stream` - Body:SQLite 文件二进制(`face_gallery.db`) @@ -104,9 +117,11 @@ GUI 侧以 `instances[]` 为“通道列表”。 保存位置:`/face_gallery.db` #### 4.3.2 立即生效(无需重启) + - `POST /v1/face-gallery/reload` 行为: + - agent 遍历所有 graphs,找到 `type==ai_face_recog` 的节点 - 对每个节点下发 runtime config patch:bump `gallery.reload_seq` - 节点收到后会重新加载 SQLite db @@ -118,49 +133,69 @@ GUI 侧以 `instances[]` 为“通道列表”。 > Base:`http://:`(默认 9100) ### 5.1 设备信息 + #### `GET /v1/info` + 用于设备列表/详情。 ### 5.2 运行态(只读代理) + #### `GET /v1/graphs` + #### `GET /v1/graphs/{name}` + #### `GET /v1/logs/recent?limit=200` ### 5.3 配置文件(root config) + #### `GET /v1/config` + 返回 `agent.config_path` 对应 JSON(用于导出/高级查看)。 #### `PUT /v1/config` + 上传完整 root config JSON(写盘 + reload;失败自动 rollback)。 ### 5.4 语义化配置(GUI 推荐使用) + #### `GET /v1/config/ui/schema` + 返回:可选模板列表 + 字段 schema(类型/默认/必填)。 #### `GET /v1/config/ui/state` + 返回:当前 config 映射到 GUI state(主要是 `instances[]`)+ 内置模板列表。 #### `POST /v1/config/ui/plan` + 输入 desired state(instances 列表),返回生成 config 与 diff。 #### `POST /v1/config/ui/apply` + 同 plan,但会写盘并 reload(失败自动 rollback)。 ### 5.5 模型管理(可选,但建议 GUI 支持) + #### `PUT /v1/models/{name}` + 上传模型(.rknn),返回可引用的 `path`。 #### `GET /v1/models` + 列出已上传模型(包含 `name/path/sha256/mtime_ms`)。 ### 5.6 人脸库 + #### `GET /v1/face-gallery` + 返回当前 db 文件信息(exists/size/mtime/path)。 #### `PUT /v1/face-gallery` + 上传 `face_gallery.db`。 #### `POST /v1/face-gallery/reload` + 让所有 `ai_face_recog` 节点热加载新 db。 --- @@ -198,6 +233,7 @@ GUI 侧以 `instances[]` 为“通道列表”。 ``` 说明: + - `global/queue` 可省略:agent 会沿用当前 config 中的值。 - `instances` 为全量期望状态:控制端应把当前列表 + 修改后的列表一起提交。 - 当前实现会生成新的 root config(只包含 `global/queue/templates/instances`),不会保留 `graphs`。 @@ -220,20 +256,25 @@ GUI 侧以 `instances[]` 为“通道列表”。 > 模板名来自 `GET /v1/config/ui/schema` 的 `templates[]`。 ### 7.1 `transcode_rtsp_hls` + - 必填:`url` - 常用:`fps,src_w,src_h,gop,bitrate_kbps,rtsp_port,hls_path` ### 7.2 `yolo_rtsp_hls` + - 必填:`url, model_path` ### 7.3 `yolo_alarm_minio` + - 必填:`url, model_path, minio_endpoint, minio_bucket, minio_ak, minio_sk` - 常用:`cooldown_ms`(默认 3000) ### 7.4 `face_det_rtsp_hls` + - 必填:`url, det_model_path` ### 7.5 `face_det_recog_rtsp_hls` + - 必填:`url, det_model_path, recog_model_path` - 默认:`gallery_path=./models/face_gallery.db`,`thr_accept=0.45`,`thr_margin=0.05` @@ -242,11 +283,13 @@ GUI 侧以 `instances[]` 为“通道列表”。 ## 8. 人脸库路径对齐建议(避免“上传了但识别不到”) 1) 默认推荐(最省事): + - media-server work_dir:`/opt/rk3588sys` - agent.models_dir:`/opt/rk3588sys/models` - ai_face_recog.gallery.path:`./models/face_gallery.db` -2) 若你们的 work_dir/models_dir 不是这种关系: +1) 若你们的 work_dir/models_dir 不是这种关系: + - 控制端在 instances params 里把 `gallery_path` 设置为**绝对路径**(例如 `/opt/rk3588sys/models/face_gallery.db`)。 --- diff --git a/Readme.md b/Readme.md index 4abe207..2c296c3 100644 --- a/Readme.md +++ b/Readme.md @@ -1,6 +1,7 @@ # PRD ③ 管理端后端(Go managerd)V1 ## 1. 目标与运行方式 + - 提供本机 HTTP API 给 React UI 使用。 - 负责 UDP 广播发现(Option A),维护设备缓存与在线状态。 - 通过设备端 `rk3588-agent` 完成配置/模型等运维操作,并可通过 agent 代理读取 graphs/logs。 @@ -9,6 +10,7 @@ 运行:单可执行 `managerd`,默认监听 `127.0.0.1:18080`(可配置)。 ## 2. 外部依赖与约束 + - Go 版本:>= 1.22(建议) - 标准库优先;Web 框架可选 `chi`/`gin`(建议 chi + net/http)。 - 不需要数据库(V1 用内存 + 可选本地 JSON 持久化)。 @@ -16,17 +18,20 @@ ## 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: @@ -34,12 +39,14 @@ - 可预留 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` @@ -52,28 +59,39 @@ ## 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` @@ -81,28 +99,39 @@ Response:包含 `info`、`graphs_summary`、`last_seen`。 - `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", @@ -110,25 +139,32 @@ Request: "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` @@ -138,7 +174,9 @@ Event `device_update` data: - `VALIDATION_ERROR` ## 6. 配置文件(managerd)建议 + `managerd.json`: + ```json { "listen": "127.0.0.1:18080", @@ -151,6 +189,7 @@ Event `device_update` data: ``` ## 7. 验收标准 + 1. Search 可发现设备并更新 registry;离线判断正确。 2. 可通过 agent 读取 graphs/logs(`GET /v1/graphs`、`GET /v1/logs/recent`)。 3. 单设备 `config/apply`、`reload`、`rollback` 可用,错误可定位。 diff --git a/docs/离线部署文档.md b/docs/离线部署文档.md new file mode 100644 index 0000000..117356b --- /dev/null +++ b/docs/离线部署文档.md @@ -0,0 +1,854 @@ +# 3588AdminBackend 离线部署文档 + +> **目标环境**: Ubuntu 22.04.5 LTS (离线环境,无法连接互联网) +> **部署方式**: 通过光盘/USB等介质拷贝安装包进行离线部署 +> **版本**: V1.0 + +--- + +## 目录 + +1. [部署概述](#1-部署概述) +2. [准备环境(有网络)](#2-准备环境有网络) +3. [打包步骤](#3-打包步骤) +4. [离线安装(生产环境)](#4-离线安装生产环境) +5. [验证与启动](#5-验证与启动) +6. [常见问题排查](#6-常见问题排查) + +--- + +## 1. 部署概述 + +### 1.1 项目简介 + +3588AdminBackend 是 Orange Pi 3588 媒体服务器的后台管理端,提供以下功能: + +- 设备发现与注册管理 +- 设备配置下发与批量任务管理 +- 代理调用设备端 API +- SSE 实时任务进度推送 + +### 1.2 技术栈 + +| 组件 | 版本 | 说明 | +|------|------|------| +| Go | 1.23+ | 运行时/编译环境 | +| chi | v5.2.3 | Web 框架 | +| cors | v1.2.2 | CORS 中间件 | +| uuid | v1.6.0 | UUID 生成库 | + +### 1.3 部署流程概览 + +``` +┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ +│ 联网机器准备 │ --> │ 打包到光盘 │ --> │ 离线环境部署 │ +│ (下载依赖/编译) │ │ /USB/ISO │ │ (Ubuntu 22.04) │ +└─────────────────┘ └─────────────────┘ └─────────────────┘ +``` + +--- + +## 2. 准备环境(有网络) + +> **说明**: 此步骤需要在有网络连接的机器上执行,用于下载所有必要的依赖包和编译二进制文件。 + +### 2.1 系统要求 + +- **操作系统**: Ubuntu 22.04+ / Debian 12+ / CentOS 8+ (x86_64 或 ARM64) +- **网络**: 可访问互联网 +- **磁盘空间**: 至少 2GB 可用空间 +- **Go 版本**: 1.23.3 或更高 + +### 2.2 安装 Go 编译环境 + +```bash +# 下载 Go 1.23.3 (根据你的架构选择) +# 方式1: AMD64 架构 +wget https://go.dev/dl/go1.23.3.linux-amd64.tar.gz + +# 方式2: ARM64 架构 (如使用 ARM 服务器) +wget https://go.dev/dl/go1.23.3.linux-arm64.tar.gz + +# 解压到 /usr/local +sudo tar -C /usr/local -xzf go1.23.3.linux-amd64.tar.gz + +# 配置环境变量 +echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.bashrc +source ~/.bashrc + +# 验证安装 +go version +# 输出: go version go1.23.3 linux/amd64 +``` + +### 2.3 克隆/准备项目源码 + +```bash +# 创建工作目录 +mkdir -p ~/3588admin-build +cd ~/3588admin-build + +# 如果有 Git 仓库,克隆代码 +git clone <你的仓库地址> 3588AdminBackend +cd 3588AdminBackend + +# 如果没有 Git,直接复制项目源码到此目录 +# cp -r /path/to/3588AdminBackend/* . +``` + +### 2.4 下载 Go 模块依赖 + +```bash +# 设置 GOPROXY 加速下载(可选,推荐) +export GOPROXY=https://goproxy.cn,direct + +# 下载所有依赖到本地 +cd ~/3588admin-build/3588AdminBackend +go mod download + +# 验证依赖完整性 +go mod verify +``` + +### 2.5 编译项目 + +```bash +# 进入项目目录 +cd ~/3588admin-build/3588AdminBackend + +# 编译 Linux AMD64 版本(生产环境是 x86_64) +GOOS=linux GOARCH=amd64 go build -o managerd-linux-amd64 ./cmd/managerd + +# 如需 ARM64 版本(可选) +# GOOS=linux GOARCH=arm64 go build -o managerd-linux-arm64 ./cmd/managerd + +# 验证编译结果 +ls -lh managerd-linux-amd64 +file managerd-linux-amd64 +``` + +### 2.6 收集依赖的 Debian 包(可选但推荐) + +如果生产环境缺少基础运行库,需要预先下载: + +```bash +# 创建依赖包目录 +mkdir -p ~/3588admin-build/deb-deps + +# 更新包列表 +sudo apt-get update + +# 下载基础依赖(Go 静态编译通常不需要,但以防万一) +cd ~/3588admin-build/deb-deps + +# 下载 ca-certificates(HTTPS 调用需要) +apt-get download ca-certificates + +# 如果需要 systemd 服务支持 +apt-get download systemd systemd-sysv + +# 列出已下载的 deb 包 +ls -la ~/3588admin-build/deb-deps/ +``` + +--- + +## 3. 打包步骤 + +### 3.1 创建部署包目录结构 + +```bash +cd ~/3588admin-build +mkdir -p 3588admin-deploy/{bin,config,scripts,docs,deps} +``` + +### 3.2 复制必要文件 + +```bash +# 1. 复制编译好的二进制文件 +cp 3588AdminBackend/managerd-linux-amd64 3588admin-deploy/bin/managerd + +# 2. 复制配置文件 +cp 3588AdminBackend/managerd.json 3588admin-deploy/config/managerd.json.example + +# 3. 复制模板文件(如果程序需要读取外部模板) +cp -r 3588AdminBackend/templates 3588admin-deploy/ 2>/dev/null || echo "无外部模板目录" + +# 4. 复制依赖包(如有) +cp deb-deps/*.deb 3588admin-deploy/deps/ 2>/dev/null || echo "无 deb 依赖包" + +# 5. 复制文档 +cp 3588AdminBackend/Readme.md 3588admin-deploy/docs/ +cp 3588AdminBackend/API_Device_RemoteMgmt_InterfaceTable.md 3588admin-deploy/docs/ 2>/dev/null || true +``` + +### 3.3 创建部署脚本 + +创建启动脚本: + +```bash +cat > 3588admin-deploy/scripts/start.sh << 'EOF' +#!/bin/bash +# 3588AdminBackend 启动脚本 + +set -e + +# 配置 +APP_NAME="managerd" +APP_DIR="$(cd "$(dirname "$0")/.." && pwd)" +BIN_PATH="$APP_DIR/bin/$APP_NAME" +CONFIG_PATH="$APP_DIR/config/managerd.json" +LOG_DIR="$APP_DIR/logs" +PID_FILE="$APP_DIR/$APP_NAME.pid" + +# 创建日志目录 +mkdir -p "$LOG_DIR" + +# 检查配置文件 +if [ ! -f "$CONFIG_PATH" ]; then + echo "错误: 配置文件不存在: $CONFIG_PATH" + echo "请先复制 config/managerd.json.example 为 config/managerd.json 并修改配置" + exit 1 +fi + +# 检查是否已在运行 +if [ -f "$PID_FILE" ]; then + PID=$(cat "$PID_FILE") + if ps -p "$PID" > /dev/null 2>&1; then + echo "错误: $APP_NAME 已在运行 (PID: $PID)" + exit 1 + else + rm -f "$PID_FILE" + fi +fi + +# 启动服务 +echo "启动 $APP_NAME..." +nohup "$BIN_PATH" -config "$CONFIG_PATH" > "$LOG_DIR/$APP_NAME.log" 2>&1 & +PID=$! +echo $PID > "$PID_FILE" + +# 等待启动 +sleep 2 +if ps -p "$PID" > /dev/null 2>&1; then + echo "启动成功! PID: $PID" + echo "日志: $LOG_DIR/$APP_NAME.log" + echo "API 地址: http://127.0.0.1:18080" +else + echo "启动失败,请检查日志" + rm -f "$PID_FILE" + exit 1 +fi +EOF +chmod +x 3588admin-deploy/scripts/start.sh +``` + +创建停止脚本: + +```bash +cat > 3588admin-deploy/scripts/stop.sh << 'EOF' +#!/bin/bash +# 3588AdminBackend 停止脚本 + +APP_NAME="managerd" +APP_DIR="$(cd "$(dirname "$0")/.." && pwd)" +PID_FILE="$APP_DIR/$APP_NAME.pid" + +if [ ! -f "$PID_FILE" ]; then + echo "$APP_NAME 未在运行" + exit 0 +fi + +PID=$(cat "$PID_FILE") +if ps -p "$PID" > /dev/null 2>&1; then + echo "停止 $APP_NAME (PID: $PID)..." + kill "$PID" + + # 等待进程结束 + for i in {1..10}; do + if ! ps -p "$PID" > /dev/null 2>&1; then + echo "已停止" + rm -f "$PID_FILE" + exit 0 + fi + sleep 1 + done + + # 强制结束 + echo "强制结束进程..." + kill -9 "$PID" 2>/dev/null || true + rm -f "$PID_FILE" + echo "已停止" +else + echo "进程不存在,清理 PID 文件" + rm -f "$PID_FILE" +fi +EOF +chmod +x 3588admin-deploy/scripts/stop.sh +``` + +创建状态检查脚本: + +```bash +cat > 3588admin-deploy/scripts/status.sh << 'EOF' +#!/bin/bash +# 3588AdminBackend 状态检查脚本 + +APP_NAME="managerd" +APP_DIR="$(cd "$(dirname "$0")/.." && pwd)" +PID_FILE="$APP_DIR/$APP_NAME.pid" +CONFIG_PATH="$APP_DIR/config/managerd.json" + +echo "========== 3588AdminBackend 状态 ==========" +echo "应用目录: $APP_DIR" +echo "配置文件: $CONFIG_PATH" + +if [ -f "$PID_FILE" ]; then + PID=$(cat "$PID_FILE") + if ps -p "$PID" > /dev/null 2>&1; then + echo "运行状态: 运行中 (PID: $PID)" + echo "进程信息:" + ps -p "$PID" -o pid,ppid,cmd,%cpu,%mem --no-headers + + # 检查端口监听 + echo "" + echo "端口监听:" + netstat -tlnp 2>/dev/null | grep "$PID/" || ss -tlnp | grep "$PID" + else + echo "运行状态: 未运行 (PID 文件存在但进程不存在)" + fi +else + echo "运行状态: 未运行" +fi + +echo "" +echo "日志文件:" +ls -lh "$APP_DIR/logs/" 2>/dev/null || echo " 无日志文件" +EOF +chmod +x 3588admin-deploy/scripts/status.sh +``` + +创建安装脚本: + +```bash +cat > 3588admin-deploy/install.sh << 'EOF' +#!/bin/bash +# 3588AdminBackend 离线安装脚本 + +set -e + +INSTALL_DIR="${1:-/opt/3588admin}" +CURRENT_DIR="$(cd "$(dirname "$0")" && pwd)" + +echo "========== 3588AdminBackend 离线安装 ==========" +echo "安装目录: $INSTALL_DIR" +echo "" + +# 检查 root 权限 +if [ "$EUID" -ne 0 ]; then + echo "请使用 sudo 运行安装脚本" + exit 1 +fi + +# 1. 安装依赖包(如果有) +if [ -d "$CURRENT_DIR/deps" ] && [ "$(ls -A $CURRENT_DIR/deps/*.deb 2>/dev/null)" ]; then + echo "[1/5] 安装依赖包..." + dpkg -i "$CURRENT_DIR/deps"/*.deb || true + apt-get install -f -y || true +else + echo "[1/5] 跳过依赖包安装 (无依赖包)" +fi + +# 2. 创建安装目录 +echo "[2/5] 创建安装目录..." +mkdir -p "$INSTALL_DIR" +cp -r "$CURRENT_DIR"/* "$INSTALL_DIR/" + +# 3. 设置权限 +echo "[3/5] 设置权限..." +chmod +x "$INSTALL_DIR/bin/managerd" +chmod +x "$INSTALL_DIR/scripts/"*.sh +mkdir -p "$INSTALL_DIR/logs" + +# 4. 初始化配置文件 +echo "[4/5] 初始化配置文件..." +if [ ! -f "$INSTALL_DIR/config/managerd.json" ]; then + cp "$INSTALL_DIR/config/managerd.json.example" "$INSTALL_DIR/config/managerd.json" + echo " 已创建默认配置文件" + echo " 请编辑 $INSTALL_DIR/config/managerd.json 修改配置(特别是 agent_token)" +else + echo " 配置文件已存在,保留现有配置" +fi + +# 5. 创建快捷方式 +echo "[5/5] 创建快捷方式..." +ln -sf "$INSTALL_DIR/scripts/start.sh" /usr/local/bin/3588admin-start 2>/dev/null || true +ln -sf "$INSTALL_DIR/scripts/stop.sh" /usr/local/bin/3588admin-stop 2>/dev/null || true +ln -sf "$INSTALL_DIR/scripts/status.sh" /usr/local/bin/3588admin-status 2>/dev/null || true + +echo "" +echo "========== 安装完成 ==========" +echo "安装目录: $INSTALL_DIR" +echo "" +echo "使用命令:" +echo " 3588admin-start - 启动服务" +echo " 3588admin-stop - 停止服务" +echo " 3588admin-status - 查看状态" +echo "" +echo "或者直接使用:" +echo " $INSTALL_DIR/scripts/start.sh" +echo " $INSTALL_DIR/scripts/stop.sh" +echo " $INSTALL_DIR/scripts/status.sh" +echo "" +echo "重要提示:" +echo " 1. 请先编辑配置文件: $INSTALL_DIR/config/managerd.json" +echo " 2. 务必修改 agent_token 为安全的随机字符串" +echo " 3. 如需监听外部地址,修改 listen 配置项" +echo " 4. 确保防火墙开放 discovery_port (默认 35688/UDP)" +EOF +chmod +x 3588admin-deploy/install.sh +``` + +### 3.4 创建 Systemd 服务文件(可选) + +```bash +mkdir -p 3588admin-deploy/systemd +cat > 3588admin-deploy/systemd/3588admin.service << 'EOF' +[Unit] +Description=3588AdminBackend Service +After=network.target + +[Service] +Type=simple +User=root +WorkingDirectory=/opt/3588admin +ExecStart=/opt/3588admin/bin/managerd -config /opt/3588admin/config/managerd.json +Restart=on-failure +RestartSec=5 + +[Install] +WantedBy=multi-user.target +EOF +``` + +### 3.5 创建版本信息文件 + +```bash +cat > 3588admin-deploy/VERSION << 'EOF' +3588AdminBackend 离线部署包 +版本: 1.0.0 +构建时间: $(date '+%Y-%m-%d %H:%M:%S') +Go版本: 1.23.3 +目标系统: Ubuntu 22.04.5 LTS x86_64 +EOF +``` + +### 3.6 打包为 tar.gz 或 ISO + +```bash +cd ~/3588admin-build + +# 方式1: 打包为 tar.gz(推荐,可刻录到光盘) +tar -czf 3588AdminBackend-离线部署包-$(date +%Y%m%d).tar.gz 3588admin-deploy/ + +# 方式2: 创建 ISO 镜像(如需刻录光盘) +# sudo apt-get install -y genisoimage +# genisoimage -o 3588AdminBackend-离线部署包-$(date +%Y%m%d).iso -R -J 3588admin-deploy/ + +echo "打包完成!" +ls -lh ~/3588admin-build/*.{tar.gz,iso} 2>/dev/null +``` + +### 3.7 最终包结构 + +``` +3588admin-deploy/ +├── bin/ +│ └── managerd # 主程序二进制文件 +├── config/ +│ └── managerd.json.example # 配置文件示例 +├── scripts/ +│ ├── start.sh # 启动脚本 +│ ├── stop.sh # 停止脚本 +│ ├── status.sh # 状态检查脚本 +│ └── install.sh # 安装脚本 +├── deps/ # 依赖 deb 包(可选) +├── docs/ # 文档 +│ ├── Readme.md +│ └── API_Device_RemoteMgmt_InterfaceTable.md +├── systemd/ +│ └── 3588admin.service # systemd 服务文件 +├── templates/ # 模板文件(如需要) +└── VERSION # 版本信息 +``` + +--- + +## 4. 离线安装(生产环境) + +> **环境**: Ubuntu 22.04.5 LTS,无网络连接 + +### 4.1 准备介质 + +将打包好的文件拷贝到光盘/USB,然后挂载到生产环境: + +```bash +# 插入光盘后挂载(通常会自动挂载) +# 或者手动挂载光盘 +sudo mkdir -p /mnt/cdrom +sudo mount /dev/cdrom /mnt/cdrom + +# 或者挂载 USB +# sudo mount /dev/sdb1 /mnt/usb + +# 查看内容 +ls /mnt/cdrom/ +``` + +### 4.2 解压部署包 + +```bash +# 创建临时目录 +mkdir -p ~/3588admin-install +cd ~/3588admin-install + +# 从光盘复制部署包 +cp /mnt/cdrom/3588AdminBackend-离线部署包-*.tar.gz . + +# 解压 +tar -xzf 3588AdminBackend-离线部署包-*.tar.gz + +# 进入部署目录 +cd 3588admin-deploy +``` + +### 4.3 执行安装 + +```bash +# 使用安装脚本(推荐) +sudo ./install.sh /opt/3588admin + +# 或者指定自定义安装路径 +# sudo ./install.sh /usr/local/3588admin +``` + +安装脚本会自动完成: + +- 安装依赖包(如有) +- 复制文件到安装目录 +- 设置执行权限 +- 创建配置文件 +- 创建命令快捷方式 + +### 4.4 手动安装(如不使用 install.sh) + +```bash +# 1. 创建安装目录 +sudo mkdir -p /opt/3588admin + +# 2. 复制文件 +sudo cp -r ~/3588admin-install/3588admin-deploy/* /opt/3588admin/ + +# 3. 设置权限 +sudo chmod +x /opt/3588admin/bin/managerd +sudo chmod +x /opt/3588admin/scripts/*.sh +sudo mkdir -p /opt/3588admin/logs + +# 4. 创建配置文件 +sudo cp /opt/3588admin/config/managerd.json.example /opt/3588admin/config/managerd.json + +# 5. 创建快捷方式(可选) +sudo ln -sf /opt/3588admin/scripts/start.sh /usr/local/bin/3588admin-start +sudo ln -sf /opt/3588admin/scripts/stop.sh /usr/local/bin/3588admin-stop +sudo ln -sf /opt/3588admin/scripts/status.sh /usr/local/bin/3588admin-status +``` + +### 4.5 配置 Systemd 服务(可选但推荐) + +```bash +# 复制服务文件 +sudo cp /opt/3588admin/systemd/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": "127.0.0.1:18080", // HTTP API 监听地址 + "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 +``` + +**方式2: 使用 Systemd** + +```bash +sudo systemctl start 3588admin +sudo systemctl status 3588admin +``` + +**方式3: 直接运行** + +```bash +sudo /opt/3588admin/bin/managerd -config /opt/3588admin/config/managerd.json +``` + +### 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 启动失败 + +**问题**: 执行 start.sh 提示启动失败 + +**排查步骤**: + +```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.2 端口被占用 + +**问题**: 提示端口 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.3 无法发现设备 + +**问题**: 设备发现功能不工作 + +**排查**: + +```bash +# 检查 UDP 端口监听 +sudo netstat -ulnp | grep 35688 + +# 检查防火墙 +sudo ufw status | grep 35688 + +# 检查网络接口是否有权限发送广播 +# 可能需要以 root 运行 + +# 检查设备端是否配置了正确的发现端口和 token +``` + +### 6.4 权限问题 + +**问题**: 提示 Permission denied + +**解决**: + +```bash +# 修复权限 +sudo chmod +x /opt/3588admin/bin/managerd +sudo chmod +x /opt/3588admin/scripts/*.sh + +# 确保以 root 运行(需要绑定低端口或发送广播时) +sudo /opt/3588admin/scripts/start.sh +``` + +### 6.5 配置文件错误 + +**问题**: 提示配置文件解析失败 + +**排查**: + +```bash +# 验证 JSON 格式 +python3 -m json.tool /opt/3588admin/config/managerd.json + +# 检查是否有注释(JSON 不支持注释) +# 如有注释需要删除 + +# 从示例重新创建 +cp /opt/3588admin/config/managerd.json.example /opt/3588admin/config/managerd.json.new +# 然后手动迁移配置 +``` + +### 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. 目录结构参考 + +安装完成后的目录结构: + +``` +/opt/3588admin/ +├── bin/ +│ └── managerd # 主程序 +├── config/ +│ └── managerd.json # 配置文件 +├── logs/ +│ └── managerd.log # 运行日志 +├── scripts/ +│ ├── start.sh # 启动脚本 +│ ├── stop.sh # 停止脚本 +│ └── status.sh # 状态脚本 +└── systemd/ + └── 3588admin.service # 服务文件 +``` + +### B. 环境变量 + +程序支持以下环境变量: + +| 变量名 | 说明 | 示例 | +|--------|------|------| +| `MANAGERD_CONFIG` | 指定配置文件路径 | `/etc/3588admin/config.json` | + +### C. 升级步骤 + +如需升级到新版本: + +```bash +# 1. 停止服务 +sudo 3588admin-stop +# 或 +sudo systemctl stop 3588admin + +# 2. 备份配置 +cp /opt/3588admin/config/managerd.json ~/managerd.json.bak + +# 3. 重复安装步骤,解压新版本 + +# 4. 恢复配置 +cp ~/managerd.json.bak /opt/3588admin/config/managerd.json + +# 5. 启动服务 +sudo 3588admin-start +``` + +### D. 完全卸载 + +```bash +# 1. 停止服务 +sudo 3588admin-stop +sudo systemctl stop 3588admin 2>/dev/null || true +sudo systemctl disable 3588admin 2>/dev/null || true + +# 2. 删除文件 +sudo rm -rf /opt/3588admin +sudo rm -f /usr/local/bin/3588admin-* +sudo rm -f /etc/systemd/system/3588admin.service + +# 3. 重新加载 systemd +sudo systemctl daemon-reload + +echo "卸载完成" +``` + +--- + +**文档版本**: 1.0 +**最后更新**: $(date '+%Y-%m-%d') +**适用版本**: 3588AdminBackend V1.0+ diff --git a/plan.md b/plan.md index 64c24cf..d1d92af 100644 --- a/plan.md +++ b/plan.md @@ -1,29 +1,35 @@ # Manager Backend (Go) 开发计划 ## 阶段 1:核心模型与设备发现 (Discovery & Registry) [DONE] + - [x] 定义核心数据结构 (`Device`, `Registry`, `Task`) - [x] 实现 UDP 广播发现逻辑 (`Discovery`模块) - [x] 实现内存设备注册表,支持并发安全与离线判定 (`Registry` 模块) - [x] 暴露基础 API:`POST /api/discovery/search` 和 `GET /api/devices` ## 阶段 2:设备客户端与代理操作 (Device Client & Action Proxy) [DONE] + - [x] 实现统一的 `AgentClient`用于与 `rk3588-agent` 通信 - [x] 实现代理接口:`reload`, `rollback`, `graphs`, `logs` - [x] 实现单台设备的 `config/apply` ## 阶段 3:任务运行器与 SSE 推送 (Task Runner & SSE) [DONE] + - [x] 实现任务调度逻辑,支持并发控制 (Concurrency) - [x] 实现 SSE (`/api/tasks/:id/events`) 实时推送任务状态 - [x] 支持批量 `config_apply` 任务 ## 阶段 4:模板管理与配置生成 (Templates & Config) [DONE] + - [x] 实现内置/本地模板读取 - [x] 实现基于模板的 Root Config 生成逻辑 ## 阶段 5:文件操作与持久化 (Model Upload & Persistence) [DONE] + - [x] 实现 `model_upload` 转发逻辑 - [x] (可选) 实现 Registry 的本地 JSON 持久化,防止重启丢失 ## 阶段 6:系统集成与完善 [DONE] + - [x] 整合所有模块并进行最终测试 - [x] 优化错误码返回,确保符合 PRD 规范 diff --git a/scripts/deploy/3588admin.service b/scripts/deploy/3588admin.service new file mode 100644 index 0000000..43bfeef --- /dev/null +++ b/scripts/deploy/3588admin.service @@ -0,0 +1,31 @@ +[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 -config /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 diff --git a/scripts/deploy/Manual.md b/scripts/deploy/Manual.md new file mode 100644 index 0000000..323dabc --- /dev/null +++ b/scripts/deploy/Manual.md @@ -0,0 +1,516 @@ +# 3588AdminBackend 部署脚本使用说明 + +> 本目录包含 3588AdminBackend 的所有部署相关脚本,支持离线环境下的安装、升级、卸载和日常运维。 + +--- + +## 目录 + +1. [快速开始](#快速开始) +2. [脚本清单](#脚本清单) +3. [详细使用指南](#详细使用指南) +4. [典型使用场景](#典型使用场景) +5. [常见问题](#常见问题) + +--- + +## 快速开始 + +### 第一次部署(离线环境) + +```bash +# 1. 挂载光盘/USB 后进入目录 +cd /mnt/cdrom/3588admin-deploy + +# 2. 检查环境 +sudo ./scripts/check-env.sh + +# 3. 执行安装 +sudo ./scripts/install.sh + +# 4. 修改配置 +sudo nano /opt/3588admin/config/managerd.json + +# 5. 启动服务 +sudo 3588admin-start + +# 6. 查看状态 +sudo 3588admin-status +``` + +--- + +## 脚本清单 + +| 脚本 | 用途 | 执行位置 | +|------|------|----------| +| `build-offline-package.sh` | 构建离线部署包 | 联网机器 | +| `check-env.sh` | 环境检查 | 目标机器 | +| `install.sh` | 安装服务 | 目标机器 | +| `uninstall.sh` | 卸载服务 | 目标机器 | +| `upgrade.sh` | 升级服务 | 目标机器 | +| `start.sh` | 启动服务 | 目标机器 | +| `stop.sh` | 停止服务 | 目标机器 | +| `status.sh` | 查看状态 | 目标机器 | +| `3588admin.service` | Systemd 服务文件 | 安装时复制 | + +--- + +## 详细使用指南 + +### 1. build-offline-package.sh + +**用途**: 在联网机器上构建完整的离线部署包 + +**执行环境**: 有网络的 Linux 机器(Ubuntu/Debian/CentOS) + +**前置条件**: +- Go 1.23+ 已安装 +- 项目源码完整 + +**使用方法**: +```bash +# 在项目目录下执行 +cd scripts/deploy +sudo ./build-offline-package.sh + +# 输出位置: build/3588AdminBackend-离线部署包-YYYYMMDD.tar.gz +``` + +**输出内容**: +``` +build/3588AdminBackend-离线部署包-20260225/ +├── bin/managerd # 编译好的二进制 +├── config/ # 配置文件 +├── scripts/ # 部署脚本 +├── systemd/ # 服务文件 +├── docs/ # 文档 +├── deps/ # 依赖包(可选) +├── VERSION # 版本信息 +└── README-离线安装.txt # 快速安装指南 +``` + +--- + +### 2. check-env.sh + +**用途**: 检查目标系统是否满足运行要求 + +**执行环境**: 目标 Ubuntu 22.04 服务器 + +**检查项**: +- 操作系统版本 +- CPU 架构 +- 端口占用情况(18080/TCP, 35688/UDP) +- 防火墙配置 +- 磁盘空间 +- 必要工具 + +**使用方法**: +```bash +# 安装前检查 +sudo ./scripts/check-env.sh +``` + +**输出示例**: +``` +========== 3588AdminBackend 环境检查 ========== + +[系统信息] + 主机名: server01 + 操作系统: Ubuntu 22.04.5 LTS + ✓ Ubuntu 22.04 detected + +[硬件信息] + 架构: x86_64 + ✓ x86_64 架构 + CPU: 4 核 + 内存: 7.7Gi + +[端口检查] + ✓ 端口 18080 可用 + ✓ 端口 35688 可用 + +... + +========== 检查总结 ========== +通过: 12 警告: 0 失败: 0 +✓ 环境检查全部通过,可以安装 +``` + +--- + +### 3. install.sh + +**用途**: 安装 3588AdminBackend 到系统 + +**语法**: +```bash +sudo ./install.sh [安装目录] +``` + +**参数**: +- `安装目录`: 可选,默认为 `/opt/3588admin` + +**使用方法**: +```bash +# 默认安装到 /opt/3588admin +sudo ./scripts/install.sh + +# 自定义安装目录 +sudo ./scripts/install.sh /usr/local/3588admin +``` + +**安装流程**: +1. 检查 root 权限 +2. 安装依赖包(如有) +3. 创建安装目录 +4. 复制二进制文件、配置、脚本 +5. 设置执行权限 +6. 创建命令快捷方式(`3588admin-start` 等) +7. 安装 Systemd 服务(可选) + +**安装后操作**: +```bash +# 编辑配置文件 +sudo nano /opt/3588admin/config/managerd.json + +# 特别注意修改: +# - agent_token: 改为安全的随机字符串 +# - listen: 如需外部访问改为 "0.0.0.0:18080" +``` + +--- + +### 4. uninstall.sh + +**用途**: 完全卸载 3588AdminBackend + +**语法**: +```bash +sudo ./uninstall.sh [安装目录] +``` + +**参数**: +- `安装目录`: 可选,默认为 `/opt/3588admin` + +**使用方法**: +```bash +# 默认卸载 +sudo ./scripts/uninstall.sh + +# 卸载自定义目录 +sudo ./scripts/uninstall.sh /usr/local/3588admin +``` + +**卸载内容**: +- 停止服务 +- 删除 Systemd 服务 +- 删除命令快捷方式 +- 删除安装目录(会自动备份配置) + +**注意**: 卸载前会自动备份 `managerd.json` 到 `/root/3588admin-backup-YYYYMMDDhhmmss/` + +--- + +### 5. upgrade.sh + +**用途**: 升级到新版本(保留配置) + +**语法**: +```bash +sudo ./upgrade.sh [安装目录] +``` + +**参数**: +- `安装目录`: 可选,默认为 `/opt/3588admin` + +**使用方法**: +```bash +# 升级流程 +# 1. 停止服务 +# 2. 备份现有数据和配置 +# 3. 更新二进制文件 +# 4. 更新脚本 +# 5. 启动服务 + +sudo ./scripts/upgrade.sh +``` + +**升级前准备**: +1. 在新的部署包中确认 `bin/managerd` 是新版本 +2. 执行升级脚本 + +**回滚方法**: +```bash +# 如升级后有问题,快速回滚 +sudo systemctl stop 3588admin +sudo cp /root/3588admin-backup-xxx/managerd.old /opt/3588admin/bin/managerd +sudo systemctl start 3588admin +``` + +--- + +### 6. start.sh + +**用途**: 启动 3588AdminBackend 服务 + +**使用方法**: +```bash +# 方式1: 使用快捷命令(推荐) +sudo 3588admin-start + +# 方式2: 直接执行 +sudo /opt/3588admin/scripts/start.sh +``` + +**功能**: +- 检查配置文件是否存在且格式正确 +- 检查端口是否被占用 +- 检查服务是否已在运行 +- 后台启动服务并记录 PID +- 显示启动结果和监听地址 + +**日志位置**: `/opt/3588admin/logs/managerd.log` + +--- + +### 7. stop.sh + +**用途**: 停止 3588AdminBackend 服务 + +**使用方法**: +```bash +# 方式1: 使用快捷命令(推荐) +sudo 3588admin-stop + +# 方式2: 直接执行 +sudo /opt/3588admin/scripts/stop.sh +``` + +**功能**: +- 优雅停止(发送 SIGTERM,等待最多 10 秒) +- 强制结束(如优雅停止失败) +- 清理 PID 文件 + +--- + +### 8. status.sh + +**用途**: 查看服务运行状态和系统信息 + +**使用方法**: +```bash +# 方式1: 使用快捷命令(推荐) +sudo 3588admin-status + +# 方式2: 直接执行 +sudo /opt/3588admin/scripts/status.sh +``` + +**显示内容**: +- 基本信息(目录、配置文件路径) +- 二进制文件状态 +- 配置文件内容和监听地址 +- 进程状态(运行/停止) +- CPU/内存使用情况 +- 网络端口监听状态 +- HTTP API 连通性测试 +- 日志文件列表和最新日志 + +--- + +### 9. 3588admin.service + +**用途**: Systemd 服务配置文件 + +**使用方法**: +```bash +# 通常由 install.sh 自动安装 +# 如需手动安装: +sudo cp scripts/3588admin.service /etc/systemd/system/ +sudo systemctl daemon-reload + +# 管理服务 +sudo systemctl start 3588admin # 启动 +sudo systemctl stop 3588admin # 停止 +sudo systemctl restart 3588admin # 重启 +sudo systemctl status 3588admin # 查看状态 +sudo systemctl enable 3588admin # 开机自启 +sudo systemctl disable 3588admin # 禁用自启 +``` + +--- + +## 典型使用场景 + +### 场景1: 首次部署 + +```bash +# 在联网机器上 +cd 3588AdminBackend/scripts/deploy +./build-offline-package.sh + +# 复制到光盘/USB,挂载到生产服务器 + +# 在生产服务器上 +sudo ./scripts/check-env.sh +sudo ./scripts/install.sh +sudo nano /opt/3588admin/config/managerd.json # 修改配置 +sudo 3588admin-start +sudo 3588admin-status +``` + +### 场景2: 日常运维 + +```bash +# 查看状态 +sudo 3588admin-status + +# 查看日志 +tail -f /opt/3588admin/logs/managerd.log + +# 重启服务 +sudo 3588admin-stop +sudo 3588admin-start + +# 或者使用 systemctl +sudo systemctl restart 3588admin +``` + +### 场景3: 版本升级 + +```bash +# 1. 在新的部署包中执行升级 +sudo ./scripts/upgrade.sh + +# 2. 验证升级 +sudo 3588admin-status + +# 3. 如出现问题,查看日志 +tail -n 50 /opt/3588admin/logs/managerd.log +``` + +### 场景4: 修改配置 + +```bash +# 1. 停止服务 +sudo 3588admin-stop + +# 2. 修改配置 +sudo nano /opt/3588admin/config/managerd.json + +# 3. 验证配置格式 +python3 -m json.tool /opt/3588admin/config/managerd.json + +# 4. 启动服务 +sudo 3588admin-start +``` + +### 场景5: 完全卸载 + +```bash +# 1. 备份配置(可选) +cp /opt/3588admin/config/managerd.json ~/managerd-backup.json + +# 2. 执行卸载 +sudo ./scripts/uninstall.sh + +# 3. 确认删除 +ls /opt/3588admin # 应提示不存在 +``` + +--- + +## 常见问题 + +### Q1: 执行脚本时提示 "Permission denied" + +**解决**: +```bash +chmod +x scripts/*.sh +sudo ./scripts/install.sh +``` + +### Q2: 安装后命令找不到(3588admin-start 等) + +**解决**: +```bash +# 检查是否创建了快捷方式 +ls -la /usr/local/bin/3588admin-* + +# 如未创建,手动创建或重新安装 +sudo ./scripts/install.sh + +# 或者使用完整路径 +sudo /opt/3588admin/scripts/start.sh +``` + +### Q3: 如何查看更详细的日志? + +**解决**: +```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 +``` + +### Q4: 服务启动后立即退出 + +**排查**: +```bash +# 1. 查看日志 +tail /opt/3588admin/logs/managerd.log + +# 2. 检查配置格式 +python3 -m json.tool /opt/3588admin/config/managerd.json + +# 3. 检查端口占用 +sudo netstat -tlnp | grep 18080 +``` + +### Q5: 如何修改监听端口? + +**解决**: +```bash +# 1. 停止服务 +sudo 3588admin-stop + +# 2. 编辑配置 +sudo nano /opt/3588admin/config/managerd.json +# 修改 "listen" 为 "127.0.0.1:18081" 或其他端口 + +# 3. 启动服务 +sudo 3588admin-start +``` + +--- + +## 文件说明 + +``` +scripts/ +├── deploy/ # 部署脚本目录 +│ ├── README.md # 本文件 +│ ├── build-offline-package.sh # 构建离线包 +│ ├── check-env.sh # 环境检查 +│ ├── install.sh # 安装 +│ ├── uninstall.sh # 卸载 +│ ├── upgrade.sh # 升级 +│ ├── start.sh # 启动 +│ ├── stop.sh # 停止 +│ ├── status.sh # 状态 +│ └── 3588admin.service # Systemd服务 +└── dev-run.sh # 开发运行脚本 +``` + +--- + +**维护者**: 运维团队 +**最后更新**: 2026-02-25 +**版本**: 1.0 diff --git a/scripts/deploy/build-offline-package.sh b/scripts/deploy/build-offline-package.sh new file mode 100644 index 0000000..a335dea --- /dev/null +++ b/scripts/deploy/build-offline-package.sh @@ -0,0 +1,207 @@ +#!/bin/bash +# 3588AdminBackend 离线部署包构建脚本 +# 在联网机器上执行,生成可刻录到光盘的部署包 + +set -e + +# 颜色定义 +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# 配置 +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +PROJECT_DIR="$(cd "$SCRIPT_DIR/../.." && pwd)" +BUILD_DIR="$PROJECT_DIR/build" +PACKAGE_NAME="3588AdminBackend-离线部署包-$(date +%Y%m%d)" +PACKAGE_DIR="$BUILD_DIR/$PACKAGE_NAME" +GO_VERSION="1.23.3" + +echo -e "${GREEN}========== 3588AdminBackend 离线部署包构建 ==========${NC}" +echo "项目目录: $PROJECT_DIR" +echo "构建目录: $BUILD_DIR" +echo "" + +# 检查命令 +command -v go >/dev/null 2>&1 || { echo -e "${RED}错误: 未找到 Go 命令${NC}"; exit 1; } + +GO_CURRENT=$(go version | awk '{print $3}') +echo -e "Go 版本: ${GREEN}$GO_CURRENT${NC}" +echo "" + +# 清理旧的构建 +echo "[1/7] 清理旧构建..." +rm -rf "$BUILD_DIR" +mkdir -p "$PACKAGE_DIR" + +# 创建目录结构 +echo "[2/7] 创建目录结构..." +mkdir -p "$PACKAGE_DIR"/{bin,config,scripts,deps,docs,systemd} + +# 编译项目 +echo "[3/7] 编译项目..." +cd "$PROJECT_DIR" + +echo " 编译 Linux AMD64 版本..." +GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o "$PACKAGE_DIR/bin/managerd" ./cmd/managerd + +echo " 验证编译结果..." +if [ ! -f "$PACKAGE_DIR/bin/managerd" ]; then + echo -e "${RED}错误: 编译失败${NC}" + exit 1 +fi + +FILE_INFO=$(file "$PACKAGE_DIR/bin/managerd") +echo " $FILE_INFO" + +# 复制配置文件 +echo "[4/7] 复制配置文件..." +if [ -f "$PROJECT_DIR/managerd.json" ]; then + cp "$PROJECT_DIR/managerd.json" "$PACKAGE_DIR/config/managerd.json.example" +else + # 创建默认配置示例 + cat > "$PACKAGE_DIR/config/managerd.json.example" << 'EOF' +{ + "listen": "127.0.0.1:18080", + "discovery_port": 35688, + "discovery_timeout_ms": 1200, + "offline_after_ms": 10000, + "agent_token": "CHANGE_ME", + "concurrency": 5 +} +EOF +fi + +# 复制模板文件(如果有) +if [ -d "$PROJECT_DIR/templates" ]; then + echo " 复制模板文件..." + cp -r "$PROJECT_DIR/templates" "$PACKAGE_DIR/" +fi + +# 复制脚本 +echo "[5/7] 复制部署脚本..." +cp "$SCRIPT_DIR/"*.sh "$PACKAGE_DIR/scripts/" +cp "$SCRIPT_DIR/3588admin.service" "$PACKAGE_DIR/systemd/" + +# 复制文档 +echo "[6/7] 复制文档..." +if [ -d "$PROJECT_DIR/docs" ]; then + cp "$PROJECT_DIR/docs"/*.md "$PACKAGE_DIR/docs/" 2>/dev/null || true +fi +if [ -f "$PROJECT_DIR/Readme.md" ]; then + cp "$PROJECT_DIR/Readme.md" "$PACKAGE_DIR/docs/" +fi +if [ -f "$PROJECT_DIR/API_Device_RemoteMgmt_InterfaceTable.md" ]; then + cp "$PROJECT_DIR/API_Device_RemoteMgmt_InterfaceTable.md" "$PACKAGE_DIR/docs/" +fi + +# 创建版本信息 +cat > "$PACKAGE_DIR/VERSION" << EOF +3588AdminBackend 离线部署包 +版本: 1.0.0 +构建时间: $(date '+%Y-%m-%d %H:%M:%S') +Go版本: $GO_CURRENT +目标系统: Ubuntu 22.04.5 LTS x86_64 +构建主机: $(hostname) +EOF + +# 创建快速安装说明 +cat > "$PACKAGE_DIR/README-离线安装.txt" << 'EOF' +╔══════════════════════════════════════════════════════════════╗ +║ 3588AdminBackend 离线部署包 - 快速安装指南 ║ +╚══════════════════════════════════════════════════════════════╝ + +【系统要求】 + - Ubuntu 22.04.5 LTS (x86_64) + - root 权限 + +【安装步骤】 + +1. 解压部署包(如需要) + tar -xzf 3588AdminBackend-离线部署包-*.tar.gz + cd 3588AdminBackend-离线部署包-*/ + +2. 执行安装脚本 + sudo ./scripts/install.sh + + 或指定自定义安装目录: + sudo ./scripts/install.sh /usr/local/3588admin + +3. 修改配置 + sudo nano /opt/3588admin/config/managerd.json + + 重点修改: + - agent_token: 修改为安全的随机字符串 + - listen: 如需外部访问改为 "0.0.0.0:18080" + +4. 启动服务 + sudo 3588admin-start + + 或 Systemd 方式: + sudo systemctl start 3588admin + sudo systemctl enable 3588admin # 开机自启 + +5. 验证安装 + sudo 3588admin-status + curl http://127.0.0.1:18080/api/devices + +【常用命令】 + 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 发现 + +EOF + +# 打包 +echo "[7/7] 打包..." +cd "$BUILD_DIR" + +echo " 创建 tar.gz 包..." +tar -czf "${PACKAGE_NAME}.tar.gz" "$PACKAGE_NAME/" + +echo " 创建 zip 包(可选)..." +if command -v zip >/dev/null 2>&1; then + zip -r "${PACKAGE_NAME}.zip" "$PACKAGE_NAME/" >/dev/null 2>&1 + ZIP_CREATED=true +else + ZIP_CREATED=false +fi + +# 计算校验和 +echo " 生成校验和..." +cd "$BUILD_DIR" +sha256sum "${PACKAGE_NAME}.tar.gz" > "${PACKAGE_NAME}.tar.gz.sha256" +if [ "$ZIP_CREATED" = true ]; then + sha256sum "${PACKAGE_NAME}.zip" > "${PACKAGE_NAME}.zip.sha256" +fi + +# 完成 +echo "" +echo -e "${GREEN}========== 构建完成 ==========${NC}" +echo "" +echo "输出文件:" +ls -lh "$BUILD_DIR/${PACKAGE_NAME}".* +echo "" +echo -e "${YELLOW}使用说明:${NC}" +echo "1. 将构建好的包刻录到光盘或复制到 USB" +echo "2. 挂载到目标 Ubuntu 22.04 服务器" +echo "3. 解压并运行 sudo ./scripts/install.sh" +echo "" +echo -e "${YELLOW}验证校验和:${NC}" +echo " cd $BUILD_DIR" +echo " sha256sum -c ${PACKAGE_NAME}.tar.gz.sha256" diff --git a/scripts/deploy/check-env.sh b/scripts/deploy/check-env.sh new file mode 100644 index 0000000..5ffe606 --- /dev/null +++ b/scripts/deploy/check-env.sh @@ -0,0 +1,191 @@ +#!/bin/bash +# 3588AdminBackend 环境检查脚本 +# 用于检查目标系统是否满足运行要求 + +echo "========== 3588AdminBackend 环境检查 ==========" +echo "" + +# 颜色定义 +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' + +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 未安装 (建议使用: apt-get install curl)" +fi + +if command -v wget >/dev/null 2>&1; then + check_pass "wget 已安装" +else + check_warn "wget 未安装" +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 | grep -q ':18080 ' && echo true || echo false) + PORT_35688=$(ss -uln | 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" + if [ "$UFW_STATUS" = "active" ]; then + if ufw status | grep -q '18080'; then + check_pass "UFW 已开放 18080 端口" + else + check_warn "UFW 已启用但未开放 18080 端口" + echo " 建议执行: sudo ufw allow 18080/tcp" + fi + + if ufw status | grep -q '35688'; then + check_pass "UFW 已开放 35688 端口" + else + check_warn "UFW 已启用但未开放 35688 端口" + echo " 建议执行: sudo ufw allow 35688/udp" + fi + fi +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 [ "$DISK_AVAIL" -ge 1 ]; then + check_pass "磁盘空间充足 (${DISK_AVAIL}G 可用)" +else + check_warn "磁盘空间不足 (${DISK_AVAIL}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 + +if command -v jq >/dev/null 2>&1; then + check_pass "jq 已安装 (JSON 处理工具)" +else + echo " jq 未安装 (可选,用于 JSON 处理)" +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}" + exit 0 +else + echo -e "${GREEN}环境检查全部通过,可以安装${NC}" + exit 0 +fi diff --git a/scripts/deploy/install.sh b/scripts/deploy/install.sh new file mode 100644 index 0000000..7210d19 --- /dev/null +++ b/scripts/deploy/install.sh @@ -0,0 +1,158 @@ +#!/bin/bash +# 3588AdminBackend 离线安装脚本 +# 适用于 Ubuntu 22.04.5 LTS 离线环境 + +set -e + +INSTALL_DIR="${1:-/opt/3588admin}" +CURRENT_DIR="$(cd "$(dirname "$0")" && pwd)" +SCRIPT_DIR="$CURRENT_DIR" +BASE_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" + +echo "========== 3588AdminBackend 离线安装 ==========" +echo "安装目录: $INSTALL_DIR" +echo "" + +# 检查 root 权限 +if [ "$EUID" -ne 0 ]; then + echo "错误: 请使用 sudo 运行安装脚本" + echo "用法: sudo $0 [安装目录]" + exit 1 +fi + +# 检查安装目录 +if [ -d "$INSTALL_DIR" ] && [ "$(ls -A $INSTALL_DIR 2>/dev/null)" ]; then + echo "警告: 安装目录 $INSTALL_DIR 已存在且不为空" + read -p "是否覆盖? (y/N): " -n 1 -r + echo + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + echo "安装已取消" + exit 1 + fi + # 备份现有配置 + if [ -f "$INSTALL_DIR/config/managerd.json" ]; then + 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 + echo " 修复依赖..." + 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 "错误: 未找到 managerd 二进制文件" + echo "请确保在打包前已编译: GOOS=linux GOARCH=amd64 go build -o bin/managerd ./cmd/managerd" + 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 + +echo " 复制脚本文件..." +mkdir -p "$INSTALL_DIR/scripts" +cp "$SCRIPT_DIR/"*.sh "$INSTALL_DIR/scripts/" 2>/dev/null || true + +# 3. 设置权限 +echo "[3/5] 设置权限..." +chmod +x "$INSTALL_DIR/bin/managerd" +chmod +x "$INSTALL_DIR/scripts/"*.sh 2>/dev/null || true +mkdir -p "$INSTALL_DIR/logs" +chmod 755 "$INSTALL_DIR/logs" + +# 4. 初始化配置文件 +echo "[4/5] 初始化配置文件..." +if [ ! -f "$INSTALL_DIR/config/managerd.json" ]; then + if [ -f "$BASE_DIR/config/managerd.json.example" ]; then + cp "$BASE_DIR/config/managerd.json.example" "$INSTALL_DIR/config/managerd.json" + echo " 已创建默认配置文件" + else + # 创建默认配置文件 + cat > "$INSTALL_DIR/config/managerd.json" << 'EOF' +{ + "listen": "127.0.0.1:18080", + "discovery_port": 35688, + "discovery_timeout_ms": 1200, + "offline_after_ms": 10000, + "agent_token": "CHANGE_ME", + "concurrency": 5 +} +EOF + echo " 已创建默认配置文件" + fi + echo " ⚠️ 请编辑 $INSTALL_DIR/config/managerd.json 修改配置(特别是 agent_token)" +else + echo " 配置文件已存在,保留现有配置" +fi + +# 5. 创建快捷方式 +echo "[5/5] 创建快捷方式..." +ln -sf "$INSTALL_DIR/scripts/start.sh" /usr/local/bin/3588admin-start 2>/dev/null || true +ln -sf "$INSTALL_DIR/scripts/stop.sh" /usr/local/bin/3588admin-stop 2>/dev/null || true +ln -sf "$INSTALL_DIR/scripts/status.sh" /usr/local/bin/3588admin-status 2>/dev/null || true + +# 6. 安装 Systemd 服务(可选) +if [ -f "$SCRIPT_DIR/3588admin.service" ]; then + echo "[可选] 安装 Systemd 服务..." + cp "$SCRIPT_DIR/3588admin.service" /etc/systemd/system/ + # 更新服务文件中的路径 + sed -i "s|/opt/3588admin|$INSTALL_DIR|g" /etc/systemd/system/3588admin.service + systemctl daemon-reload + echo " 已安装 Systemd 服务" + echo " 使用命令:" + echo " systemctl start 3588admin # 启动服务" + echo " systemctl stop 3588admin # 停止服务" + echo " systemctl enable 3588admin # 开机自启" +fi + +echo "" +echo "========== 安装完成 ==========" +echo "安装目录: $INSTALL_DIR" +echo "" +echo "使用命令:" +echo " 3588admin-start - 启动服务" +echo " 3588admin-stop - 停止服务" +echo " 3588admin-status - 查看状态" +echo "" +echo "或者直接使用:" +echo " $INSTALL_DIR/scripts/start.sh" +echo " $INSTALL_DIR/scripts/stop.sh" +echo " $INSTALL_DIR/scripts/status.sh" +echo "" +echo "重要提示:" +echo " 1. 请先编辑配置文件: $INSTALL_DIR/config/managerd.json" +echo " 2. 务必修改 agent_token 为安全的随机字符串" +echo " 3. 如需监听外部地址,修改 listen 配置项" +echo " 4. 确保防火墙开放 discovery_port (默认 35688/UDP)" +echo "" +echo "首次启动前请执行:" +echo " sudo nano $INSTALL_DIR/config/managerd.json" diff --git a/scripts/deploy/start.sh b/scripts/deploy/start.sh new file mode 100644 index 0000000..428a027 --- /dev/null +++ b/scripts/deploy/start.sh @@ -0,0 +1,98 @@ +#!/bin/bash +# 3588AdminBackend 启动脚本 + +set -e + +# 配置 +APP_NAME="managerd" +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +APP_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" +BIN_PATH="$APP_DIR/bin/$APP_NAME" +CONFIG_PATH="$APP_DIR/config/managerd.json" +LOG_DIR="$APP_DIR/logs" +PID_FILE="$APP_DIR/$APP_NAME.pid" + +# 显示信息 +echo "========== 启动 3588AdminBackend ==========" +echo "应用目录: $APP_DIR" +echo "配置文件: $CONFIG_PATH" +echo "" + +# 检查二进制文件 +if [ ! -f "$BIN_PATH" ]; then + echo "错误: 未找到二进制文件: $BIN_PATH" + exit 1 +fi + +# 检查配置文件 +if [ ! -f "$CONFIG_PATH" ]; then + echo "错误: 配置文件不存在: $CONFIG_PATH" + echo "请从示例文件创建:" + echo " cp $APP_DIR/config/managerd.json.example $CONFIG_PATH" + exit 1 +fi + +# 验证 JSON 格式 +if ! python3 -m json.tool "$CONFIG_PATH" > /dev/null 2>&1; then + echo "错误: 配置文件 JSON 格式不正确" + echo "请检查: $CONFIG_PATH" + exit 1 +fi + +# 创建日志目录 +mkdir -p "$LOG_DIR" + +# 检查是否已在运行 +if [ -f "$PID_FILE" ]; then + PID=$(cat "$PID_FILE") + if ps -p "$PID" > /dev/null 2>&1; then + echo "警告: $APP_NAME 已在运行 (PID: $PID)" + echo "如需重启,请先执行 stop.sh" + exit 1 + else + echo "清理过期的 PID 文件" + rm -f "$PID_FILE" + fi +fi + +# 启动服务 +echo "正在启动 $APP_NAME..." +echo "日志文件: $LOG_DIR/$APP_NAME.log" + +# 使用 nohup 后台运行 +nohup "$BIN_PATH" -config "$CONFIG_PATH" >> "$LOG_DIR/$APP_NAME.log" 2>&1 & +PID=$! +echo $PID > "$PID_FILE" + +# 等待启动 +sleep 2 +if ps -p "$PID" > /dev/null 2>&1; then + echo "" + echo "✅ 启动成功!" + echo " PID: $PID" + echo " 日志: $LOG_DIR/$APP_NAME.log" + + # 尝试读取监听地址 + sleep 1 + if command -v ss &> /dev/null; then + LISTEN_INFO=$(ss -tlnp | grep "$PID" | head -1) + if [ -n "$LISTEN_INFO" ]; then + echo " 监听: $(echo "$LISTEN_INFO" | awk '{print $4}')" + fi + elif command -v netstat &> /dev/null; then + LISTEN_INFO=$(netstat -tlnp 2>/dev/null | grep "$PID/" | head -1) + if [ -n "$LISTEN_INFO" ]; then + echo " 监听: $(echo "$LISTEN_INFO" | awk '{print $4}')" + fi + fi + + echo "" + echo "查看日志: tail -f $LOG_DIR/$APP_NAME.log" + echo "查看状态: $0 status 或 3588admin-status" +else + echo "" + echo "❌ 启动失败" + echo "请检查日志: $LOG_DIR/$APP_NAME.log" + rm -f "$PID_FILE" + exit 1 +fi diff --git a/scripts/deploy/status.sh b/scripts/deploy/status.sh new file mode 100644 index 0000000..f561ed1 --- /dev/null +++ b/scripts/deploy/status.sh @@ -0,0 +1,154 @@ +#!/bin/bash +# 3588AdminBackend 状态检查脚本 + +APP_NAME="managerd" +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +APP_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" +PID_FILE="$APP_DIR/$APP_NAME.pid" +CONFIG_PATH="$APP_DIR/config/managerd.json" +LOG_DIR="$APP_DIR/logs" +BIN_PATH="$APP_DIR/bin/$APP_NAME" + +echo "========== 3588AdminBackend 状态 ==========" +echo "" +echo "基本信息:" +echo " 应用目录: $APP_DIR" +echo " 二进制文件: $BIN_PATH" +echo " 配置文件: $CONFIG_PATH" +echo " 日志目录: $LOG_DIR" + +# 检查二进制文件 +if [ -f "$BIN_PATH" ]; then + echo " 二进制状态: ✅ 存在" + # 显示版本信息(如果程序支持) + VERSION=$($BIN_PATH -version 2>/dev/null || echo "") + if [ -n "$VERSION" ]; then + echo " 版本: $VERSION" + fi +else + echo " 二进制状态: ❌ 不存在" +fi + +# 检查配置文件 +if [ -f "$CONFIG_PATH" ]; then + echo " 配置文件: ✅ 存在" + # 显示关键配置 + if command -v python3 &> /dev/null; then + LISTEN=$(python3 -c "import json; print(json.load(open('$CONFIG_PATH')).get('listen', 'N/A'))" 2>/dev/null) + 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 " 配置文件: ❌ 不存在" +fi + +echo "" +echo "运行状态:" + +# 检查进程 +if [ -f "$PID_FILE" ]; then + PID=$(cat "$PID_FILE") + if ps -p "$PID" > /dev/null 2>&1; then + echo " 进程状态: 🟢 运行中" + echo " PID: $PID" + + # 获取进程详细信息 + if command -v ps &> /dev/null; then + echo "" + echo "进程详情:" + ps -p "$PID" -o pid,ppid,pcpu,pmem,rss,vsz,etime,cmd --headers 2>/dev/null | while read line; do + echo " $line" + done + fi + + # 检查端口监听 + echo "" + echo "网络监听:" + if command -v ss &> /dev/null; then + LISTENERS=$(ss -tlnp | grep "$PID" || true) + if [ -n "$LISTENERS" ]; then + echo "$LISTENERS" | while read line; do + echo " TCP: $line" + done + fi + UDP_LISTENERS=$(ss -ulnp | grep "$PID" || true) + if [ -n "$UDP_LISTENERS" ]; then + echo "$UDP_LISTENERS" | while read line; do + echo " UDP: $line" + done + fi + elif command -v netstat &> /dev/null; then + LISTENERS=$(netstat -tlnp 2>/dev/null | grep "$PID/" || true) + if [ -n "$LISTENERS" ]; then + echo "$LISTENERS" | while read line; do + echo " $line" + done + fi + fi + + # 测试 API + echo "" + echo "API 测试:" + if command -v curl &> /dev/null; then + # 从配置文件中获取监听地址 + if [ -f "$CONFIG_PATH" ]; then + API_URL="http://127.0.0.1:18080/api/devices" + HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" "$API_URL" 2>/dev/null || echo "000") + if [ "$HTTP_CODE" = "200" ] || [ "$HTTP_CODE" = "401" ]; then + echo " ✅ HTTP API 响应正常 (HTTP $HTTP_CODE)" + elif [ "$HTTP_CODE" = "000" ]; then + echo " ⚠️ 无法连接 HTTP API" + else + echo " ℹ️ HTTP API 响应: $HTTP_CODE" + fi + fi + fi + + else + echo " 进程状态: 🔴 未运行 (PID 文件存在但进程不存在)" + echo " 建议: 删除过期的 PID 文件" + fi +else + # 尝试直接查找进程 + PID=$(pgrep -f "^$BIN_PATH" | head -1) + if [ -n "$PID" ]; then + echo " 进程状态: 🟡 运行中 (无 PID 文件,PID: $PID)" + echo " 建议: 重新创建 PID 文件: echo $PID > $PID_FILE" + else + echo " 进程状态: ⚫ 未运行" + fi +fi + +# 日志信息 +echo "" +echo "日志信息:" +if [ -d "$LOG_DIR" ]; then + LOG_FILES=$(ls -1 "$LOG_DIR"/*.log 2>/dev/null | head -5) + if [ -n "$LOG_FILES" ]; then + echo " 日志文件:" + ls -lh "$LOG_DIR"/*.log 2>/dev/null | tail -5 | while read line; do + echo " $line" + done + + # 显示最后几行日志 + NEWEST_LOG=$(ls -t "$LOG_DIR"/*.log 2>/dev/null | head -1) + if [ -n "$NEWEST_LOG" ]; then + echo "" + echo " 最新日志 ($NEWEST_LOG):" + tail -n 3 "$NEWEST_LOG" | while read line; do + echo " $line" + done + fi + else + echo " 无日志文件" + fi +else + echo " 日志目录不存在" +fi + +echo "" +echo "========== 操作命令 ==========" +echo " 启动: $SCRIPT_DIR/start.sh" +echo " 停止: $SCRIPT_DIR/stop.sh" +echo " 查看日志: tail -f $LOG_DIR/$APP_NAME.log" diff --git a/scripts/deploy/stop.sh b/scripts/deploy/stop.sh new file mode 100644 index 0000000..987622d --- /dev/null +++ b/scripts/deploy/stop.sh @@ -0,0 +1,69 @@ +#!/bin/bash +# 3588AdminBackend 停止脚本 + +APP_NAME="managerd" +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +APP_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" +PID_FILE="$APP_DIR/$APP_NAME.pid" + +echo "========== 停止 3588AdminBackend ==========" + +if [ ! -f "$PID_FILE" ]; then + echo "ℹ️ $APP_NAME 未在运行 (PID 文件不存在)" + + # 尝试查找进程 + PID=$(pgrep -f "^$APP_DIR/bin/$APP_NAME" | head -1) + if [ -n "$PID" ]; then + echo "发现运行中的进程 (PID: $PID),尝试停止..." + kill "$PID" 2>/dev/null || true + + for i in {1..10}; do + if ! ps -p "$PID" > /dev/null 2>&1; then + echo "✅ 已停止" + exit 0 + fi + sleep 1 + done + + echo "强制结束进程..." + kill -9 "$PID" 2>/dev/null || true + echo "✅ 已停止" + fi + exit 0 +fi + +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 "✅ 已停止" + rm -f "$PID_FILE" + exit 0 + fi + echo -n "." + sleep 1 + done + echo "" + + # 强制结束 + echo "进程未响应,强制结束..." + kill -9 "$PID" 2>/dev/null || true + sleep 1 + + if ! ps -p "$PID" > /dev/null 2>&1; then + echo "✅ 已强制停止" + else + echo "❌ 无法停止进程,请手动检查" + exit 1 + fi +else + echo "ℹ️ 进程不存在 (PID: $PID),清理 PID 文件" +fi + +rm -f "$PID_FILE" diff --git a/scripts/deploy/uninstall.sh b/scripts/deploy/uninstall.sh new file mode 100644 index 0000000..056d373 --- /dev/null +++ b/scripts/deploy/uninstall.sh @@ -0,0 +1,79 @@ +#!/bin/bash +# 3588AdminBackend 卸载脚本 + +set -e + +INSTALL_DIR="${1:-/opt/3588admin}" + +echo "========== 3588AdminBackend 卸载 ==========" +echo "安装目录: $INSTALL_DIR" +echo "" + +# 检查 root 权限 +if [ "$EUID" -ne 0 ]; then + echo "错误: 请使用 sudo 运行卸载脚本" + exit 1 +fi + +# 确认 +read -p "确定要完全卸载 3588AdminBackend? 此操作不可恢复! (y/N): " -n 1 -r +echo +if [[ ! $REPLY =~ ^[Yy]$ ]]; then + echo "卸载已取消" + exit 0 +fi + +# 1. 停止服务 +echo "[1/4] 停止服务..." +if [ -f "$INSTALL_DIR/scripts/stop.sh" ]; then + "$INSTALL_DIR/scripts/stop.sh" 2>/dev/null || true +fi + +# 停止 systemd 服务 +if systemctl is-active --quiet 3588admin 2>/dev/null; then + echo " 停止 systemd 服务..." + systemctl stop 3588admin +fi + +if systemctl is-enabled --quiet 3588admin 2>/dev/null; then + echo " 禁用开机自启..." + 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 +echo " 已删除命令快捷方式" + +# 4. 备份并删除安装目录 +echo "[4/4] 删除安装文件..." +if [ -d "$INSTALL_DIR" ]; then + # 备份配置 + BACKUP_DIR="" + 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 "========== 卸载完成 ==========" +echo "3588AdminBackend 已完全卸载" +if [ -n "$BACKUP_DIR" ]; then + echo "配置文件备份: $BACKUP_DIR/managerd.json" +fi diff --git a/scripts/deploy/upgrade.sh b/scripts/deploy/upgrade.sh new file mode 100644 index 0000000..2d6f3cf --- /dev/null +++ b/scripts/deploy/upgrade.sh @@ -0,0 +1,104 @@ +#!/bin/bash +# 3588AdminBackend 升级脚本 + +set -e + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +INSTALL_DIR="${1:-/opt/3588admin}" +BACKUP_DIR="/root/3588admin-backup-$(date +%Y%m%d%H%M%S)" + +echo "========== 3588AdminBackend 升级 ==========" +echo "安装目录: $INSTALL_DIR" +echo "备份目录: $BACKUP_DIR" +echo "" + +# 检查 root 权限 +if [ "$EUID" -ne 0 ]; then + echo "错误: 请使用 sudo 运行升级脚本" + exit 1 +fi + +# 检查安装目录是否存在 +if [ ! -d "$INSTALL_DIR" ]; then + echo "错误: 安装目录不存在: $INSTALL_DIR" + echo "请先运行 install.sh 进行首次安装" + exit 1 +fi + +# 确认 +read -p "确定要升级 3588AdminBackend? (y/N): " -n 1 -r +echo +if [[ ! $REPLY =~ ^[Yy]$ ]]; then + echo "升级已取消" + exit 0 +fi + +# 1. 停止服务 +echo "[1/5] 停止服务..." +if [ -f "$INSTALL_DIR/scripts/stop.sh" ]; then + "$INSTALL_DIR/scripts/stop.sh" 2>/dev/null || true +elif systemctl is-active --quiet 3588admin 2>/dev/null; then + systemctl stop 3588admin +fi +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 + +echo " 备份完成: $BACKUP_DIR" + +# 3. 更新二进制文件 +echo "[3/5] 更新二进制文件..." +if [ -f "$SCRIPT_DIR/../bin/managerd" ]; then + cp "$SCRIPT_DIR/../bin/managerd" "$INSTALL_DIR/bin/managerd" + chmod +x "$INSTALL_DIR/bin/managerd" + echo " 已更新二进制文件" +else + echo "警告: 未找到新的二进制文件,跳过更新" +fi + +# 4. 更新脚本 +echo "[4/5] 更新脚本..." +if [ -d "$SCRIPT_DIR" ]; then + cp "$SCRIPT_DIR/"*.sh "$INSTALL_DIR/scripts/" 2>/dev/null || true + chmod +x "$INSTALL_DIR/scripts/"*.sh + echo " 已更新脚本文件" +fi + +# 5. 启动服务 +echo "[5/5] 启动服务..." +if [ -f "$INSTALL_DIR/scripts/start.sh" ]; then + "$INSTALL_DIR/scripts/start.sh" +else + systemctl start 3588admin +fi + +echo "" +echo "========== 升级完成 ==========" +echo "服务已启动" +echo "" +echo "备份位置: $BACKUP_DIR" +echo "" +echo "如升级后出现问题,可快速回滚:" +echo " sudo systemctl stop 3588admin" +echo " sudo cp $BACKUP_DIR/managerd.old $INSTALL_DIR/bin/managerd" +echo " sudo systemctl start 3588admin" diff --git a/scripts/dev-run.sh b/scripts/dev-run.sh new file mode 100644 index 0000000..4ddbae9 --- /dev/null +++ b/scripts/dev-run.sh @@ -0,0 +1,56 @@ +#!/bin/bash +# 3588AdminBackend 开发运行脚本 +# 用于本地开发调试 + +set -e + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" +CONFIG_FILE="$PROJECT_DIR/managerd.json" + +echo "========== 3588AdminBackend 开发运行 ==========" +echo "项目目录: $PROJECT_DIR" +echo "" + +# 检查 Go 环境 +if ! command -v go >/dev/null 2>&1; then + echo "错误: 未找到 Go 命令" + exit 1 +fi + +echo "Go 版本: $(go version)" +echo "" + +# 检查配置文件 +if [ ! -f "$CONFIG_FILE" ]; then + echo "创建默认配置文件..." + cat > "$CONFIG_FILE" << 'EOF' +{ + "listen": "127.0.0.1:18080", + "discovery_port": 35688, + "discovery_timeout_ms": 1200, + "offline_after_ms": 10000, + "agent_token": "dev-token-12345", + "concurrency": 5 +} +EOF + echo "配置文件已创建: $CONFIG_FILE" + echo "请根据需要修改配置" + echo "" +fi + +# 下载依赖 +echo "[1/2] 检查依赖..." +cd "$PROJECT_DIR" +go mod download + +# 运行 +echo "[2/2] 启动服务..." +echo "配置文件: $CONFIG_FILE" +echo "API 地址: http://127.0.0.1:18080" +echo "" +echo "按 Ctrl+C 停止服务" +echo "" + +# 使用 go run 直接运行 +go run ./cmd/managerd -config "$CONFIG_FILE"