Skip to content

设备管控能力规划 ​

本文是 能力评估 + 实现蓝图(2026-07-05)。把现有「只读监控」升级为「可操作管控」:服务器/NAS/摄像头的文件操作、状态查看、电源控制、摄像头录制回放。评估已认可,本文档作为后续实现的依据。

背景与范围 ​

源自「NAS 页面能否升级为运维管理」的讨论。经过对现有代码的核对,真实需求收敛为三类设备的 8 个管控动作,而非通用运维平台(不需要 WebShell / 进程 / 容器 / 服务管理那些重活)。

设备动作
🖥️ 服务器操作文件 / 看状态 / 重启
🗄️ NAS操作文件 / 看状态 / 关机·重启
📹 摄像头实时画面 / 回放(录制)

结论:8 项中 4 项已完成、3 项低成本低扩展、真正的工程量只在「摄像头录制回放」一项。

当前能力盘点(已有资产) ​

层能力位置
主机采集SSH 跑 /proc 脚本采 CPU/内存/磁盘/网络/负载;或 Agent 上报 gopsutilssh.go、sysinfo.go
NAS 采集Agent 上报(飞牛/绿联等国产 NAS)、群晖 Synology API、TrueNAS REST API、SNMP fallbackagent_ws.go、nas_synology.go、nas_truenas.go、nas_snmp.go
摄像头实时ONVIF 取流 + RTSP→WS(jessibuca 解码)camera.go、rtsp_session.go
文件管理SMB + WebDAV + Alist + Agent 四后端filemanager/
Agent RPC双向 WS,cmd/resp/data 三通道 + caps 协商 + io.Pipe 流式agent_ws.go
凭证SSH 私钥/密码双通道,AES 加密存储,TOFU hostkeyssh.go:87-168
告警/通知阈值状态机 + 去重冷却 + 通知中心 13 类渠道alert.go + internal/notify

关键设计洞察 ​

🔑 SSH 通道已经是通用 exec ​

ssh.go:173-191 的 sshExec.Run(ctx, cmd) 早已存在,SSHCollector 一直用它跑采集脚本。这意味着 「重启服务器」根本不需要扩展协议、不需要 WebShell —— 直接复用现有 SSH 连接跑一条 sudo -n reboot 即可。

把电源操作限定为 reboot / shutdown 两个白名单动作,安全风险从「开放任意命令」降为「两个固定命令」,且无需触碰 Agent 协议。

🔑 Agent 协议可扩展但本次用不到 ​

agent_ws.go:51-61 的 AgentEnvelope 是开放结构,加 Op:exec + CapabilityExec 是约定式扩展。但 本规划范围不需要 —— 文件操作走现有 Agent 文件 RPC,电源操作走 SSH/厂商 API。Agent exec 通道留作未来「进程 kill / 容器启停」的入口。

逐项实现路径 ​

🖥️ 服务器 ​

动作现状实现工作量
操作文件🟡 看部署装了 Agent 的服务器 → 直接复用 agent.go 文件 RPC;只能 SSH 的 → 补 SFTP 后端(可后置)0 / +2-3 天
看状态✅已有0
重启🟢 极轻复用 sshExec.Run("sudo -n reboot"),加电源 API0.5-1 天

SFTP 后端(可选,后置):用 github.com/pkg/sftp(基于 golang.org/x/crypto/ssh,SSH client 已有),实现 filemanager.Backend 接口。优先推荐「服务器装 Agent 统一走 Agent 文件管理」,SFTP 仅作「只能 SSH 不能装 Agent」的兜底。

🗄️ NAS ​

动作现状实现工作量
操作文件✅SMB(群晖/威联通/飞牛原生支持)+ WebDAV0
看状态✅厂商 API 采集0
关机·重启🟢 轻见下方分发1-2 天

电源操作按 NAS 协议分发:

NAS 协议关机/重启方式
api(群晖)复用现成的 synoCall 调 SYNO.Core.System.Power,method=shutdown / reboot
api(TrueNAS)REST API POST /system/reboot / POST /system/shutdown(TrueNAS v2.0+)
snmp不支持(协议限制),UI 隐藏电源按钮
兜底SSH sudo -n shutdown

📹 摄像头 ​

动作现状实现工作量
实时画面✅已有 RTSP→WS + jessibuca0
录制回放🔴 缺口方案 B:服务端 FFmpeg 录制(见下)8-12 天

摄像头录制回放 · 方案 B 详细设计 ​

服务端常驻 FFmpeg 把 RTSP 录成 HLS 分片存盘,前端时间轴选时间 → 动态生成 m3u8 → jessibuca 播放。不依赖摄像头型号,能看历史录像。

录制格式 ​

HLS(.ts 分片,2-4 秒一片,-c copy 直拷流不重编码,省 CPU;前提是摄像头输出 H264/H265,绝大多数满足)。jessibuca 已支持 HLS,前端零新增依赖。

ffmpeg -rtsp_transport tcp -i {rtsp_url} \
  -c copy -f hls \
  -hls_time 3 -hls_list_size 0 \
  -hls_segment_filename {dir}/%Y%m%d%H%M%S.ts \
  -strftime 1 \
  {dir}/live.m3u8

存储布局 ​

{PTPATRONUS_DATA_DIR}/recordings/
  └── {camera_id}/
      └── 2026-07-05/
          ├── 140000.ts
          ├── 140003.ts
          ├── 140006.ts
          ├── ...
          └── live.m3u8          # FFmpeg 滚动写的(回放不直接用)

回放时 动态生成 m3u8(从目标时间对应的分片开始),不复用 live.m3u8。

进程管理 ​

新建 internal/nvr/ 包(不污染 monitor,避免循环依赖):

internal/nvr/
├── recorder.go        # 单路录制 supervisor:启停 FFmpeg + 退出重启 + 指数退避
├── manager.go         # cameraID → *recorder 的 map(进程内单实例,同 AgentWSHub 模式)
├── manifest.go        # 扫目录生成回放 m3u8 + 有录像时段索引
└── retention.go       # 每日清理超期录像(复用 app.go 的 cron)
  • 启动时扫表拉起所有 record_enabled=true 的摄像头
  • 摄像头增删改时动态启停(在 monitor.Service 的 target 变更回调里 hook)
  • FFmpeg 进程退出 → 指数退避重启(摄像头短暂断流不致死)
  • 全局录制路数上限(防磁盘/CPU 暴走,默认 16)

回放流程 ​

前端: 用户在时间轴点 2026-07-05 14:30:00
  ↓
GET /api/v1/monitor/cameras/:id/playback.m3u8?time=2026-07-05T14:30:00Z
  ↓
后端 manifest.go:
  1. 扫 recordings/{id}/2026-07-05/ 按文件名时间戳排序
  2. 二分定位含 14:30:00 的分片
  3. 从该分片起拼一个 m3u8(限制 N 片 = 约 N×3 秒窗口,VOD 而非 LIVE)
  4. 返回 application/vnd.apple.mpegurl
  ↓
前端 jessibuca 加载该 m3u8,常规 HLS 播放
  ← 进度条拖动 = 重新请求新 time 的 m3u8

时间轴索引 ​

GET /api/v1/monitor/cameras/:id/recordings?date=2026-07-05 → 该日有录像的时段列表([{start, end}, ...],由扫 .ts 文件名首尾聚合)。前端渲染为时间轴条的可点区段。

存储估算(必看) ​

码率单摄/小时单摄/天保留 7 天
1080p H264 ~2Mbps~900 MB~21.6 GB~150 GB
720p ~1Mbps~450 MB~10.8 GB~76 GB

4 路 1080p 录 7 天 ≈ 600 GB。必须:

  • 录制默认关闭,按摄像头粒度显式开启
  • 保留天数可配(默认 7 天)
  • 录制目录可配到独立大盘(避免撑爆系统盘)
  • UI 在开启录制时显示存储预估警示

API 设计 ​

# 录制控制
POST   /api/v1/monitor/cameras/:id/record          {enabled, retention_days}
GET    /api/v1/monitor/cameras/:id/record/status   → {recording, pid, uptime, error}

# 回放
GET    /api/v1/monitor/cameras/:id/recordings?date=YYYY-MM-DD   → 时段列表
GET    /api/v1/monitor/cameras/:id/playback.m3u8?time=RFC3339   → 动态 m3u8(直接喂 jessibuca)

# 分片静态资源(回放 m3u8 内部引用)
GET    /api/v1/monitor/recordings/{camera_id}/{date}/{file}.ts  → 文件(FileServer,带 admin 鉴权)

数据模型扩展 ​

MonitorTarget 增字段:

go
RecordEnabled  bool   `json:"record_enabled" gorm:"default:false"`
RetentionDays  int    `json:"retention_days,omitempty"`     // 默认 7
RecordProfile  string `json:"record_profile,omitempty"`     // main | sub(主/子码流)

前端 ​

  • DeviceDetail 加「电源操作」按钮组(重启/关机,二次确认)
  • 摄像头详情加「录像」开关 + 保留天数 + 存储预估
  • 摄像头详情加「回放」Tab:时间轴(按日 + 时段条) + jessibuca 播放器(复用 RtspPlayer.vue,src 切换为动态 m3u8)
  • 移动端同设计(Flutter 复用现有播放器组件)

电源操作 · 统一 API ​

POST /api/v1/monitor/targets/:id/power   {action: "reboot" | "shutdown"}   RequireAdmin

服务端按 target.type + ResolveProtocol(target) 分发到对应执行器(host→SSH、nas→厂商API、camera→不支持返回 400)。所有电源动作入库审计(新增 power_action_log 表 或 复用 system log)。

工作量与里程碑 ​

里程碑内容人天
M1 电源闭环服务器 reboot + NAS 关机/重启(SSH + 群晖 + TrueNAS)+ 前端按钮 + 审计2-3
M2 录制内核internal/nvr/ 包:FFmpeg supervisor + manager + 配置项 + 启动 hook3-4
M3 回放链路动态 m3u8 生成 + 时段索引 API + ts FileServer + TTL 清理 cron3-4
M4 前端回放时间轴组件 + 回放 Tab + 录制开关 + 存储预估(Web + Flutter)2-3
M5(可选) SFTPfilemanager SFTP 后端,给「只能 SSH」的服务器补文件操作2-3

合计:M1-M4 约 10-14 人天(含录制回放);加 M5 约 12-17 人天。

安全设计 ​

风险对策
电源操作 = 高危严格白名单 action ∈ {reboot, shutdown},不接受任意命令;RequireAdmin + 二次确认弹窗 + 入库审计
SSH sudo 权限采集脚本探测 sudo 能力,UI 提示用户配置 /etc/sudoers 的 NOPASSWD;root 登录则不需要
录制磁盘爆炸默认关闭 + 保留天数 + 全局路数上限 + 独立盘可配 + 开启时存储预估警示
回放越权m3u8/ts 端点都走 admin 鉴权;ts 路径做 safepath 钳制(复用 filemanager 的 ALLOWED_ROOTS 模式)
FFmpeg 进程失控supervisor 指数退避 + 最大重启频率;崩了不拉垮主进程

依赖 ​

依赖用途引入方式
ffmpeg(系统二进制)RTSP→HLS 录制运行时探测;Docker 镜像 apt install ffmpeg;类似 jessibuca 资源的手动部署策略
github.com/pkg/sftp(仅 M5)SFTP 文件后端纯 Go,基于已用的 golang.org/x/crypto/ssh

待决策 / 风险 ​

  1. FFmpeg 部署:服务端要装 FFmpeg。Docker 镜像需重打(加 ffmpeg),自部署需文档说明。是否接受这个新系统依赖?
  2. 录制存储位置:默认放 PTPATRONUS_DATA_DIR/recordings,还是强制要求用户配独立路径?推荐默认 + 可覆盖。
  3. 多副本部署:录制 manager 是进程内 map,多副本会重复录制。当前 PTPatronus 单副本为主,暂不处理,文档注明限制(同 AgentWSHub)。
  4. TrueNAS API 字段:关机/重启端点需真机校验(TrueNAS 版本间有差异)。
  5. 回放性能:扫目录生成 m3u8 在大量分片时可能慢,可加 manifest 缓存(按 camera+date 缓存,录制时增量更新)。

与现有模块的关系 ​

  • 不动 monitor 采集/告警/通知链路 —— 管控是叠加层
  • 复用 filemanager(Agent/SMB)、notify(电源/录制告警)、SSH 通道、jessibuca、app.go cron、safepath 模式
  • 新增 internal/nvr/ 包、电源 API handler、前端电源按钮 + 回放 Tab、MonitorTarget 字段、审计表