PON Stick Manager 使用说明

闭源 Docker 部署版。通过 Docker Hub 拉取镜像,挂载 /data 保存配置、数据库和日志。

PON Stick Manager 使用说明

PON Stick Manager 是一个用于集中监控和维护 PON Stick/ONU 猫棒的 Web 工具。它会定时 ping 设备、通过 SSH 读取猫棒信息,展示温度、收光、注册状态、EPON 模式、LOID、MAC 等数据,并提供配置写入、重启、历史曲线和异常状态跟踪。

本文档面向部署和日常使用,适合直接发布到 Cloudflare Pages 作为项目说明页。

1. 快速入门

Docker 快速启动

推荐使用 Docker 部署。创建宿主机数据目录:

mkdir -p /srv/docker/pon-stick-manager/data/logs
chmod -R 0777 /srv/docker/pon-stick-manager/data

创建 /srv/docker/pon-stick-manager/docker-compose.yml

services:
  pon-stick-manager:
    image: sky114514/pon-stick-manager:latest
    container_name: pon-stick-manager
    restart: unless-stopped
    ports:
      - "5010:8765"
    volumes:
      - /srv/docker/pon-stick-manager/data:/data
    environment:
      ONU_DATA_DIR: /data
      ONU_CONFIG: /data/config.yaml
      ONU_LOG_DIR: /data/logs
      ONU_HOST: 0.0.0.0
      ONU_PORT: 8765
      ONU_ENABLE_MOCK: "0"

启动:

cd /srv/docker/pon-stick-manager
docker compose up -d

访问:

http://宿主机IP:5010/

首次启动时,如果 /data/config.yaml 不存在,容器会自动创建空配置文件,并复制 /data/config.example.yaml。可以通过 Web 页面新增猫棒,也可以手动编辑 /srv/docker/pon-stick-manager/data/config.yaml

添加第一台猫棒

打开 Web 页面后,点击加号卡片新增猫棒,填写:

字段说明
名称展示名称,最多 20 个字符
IP猫棒管理 IP,例如 192.168.70.1
密码root SSH 登录密码,可留空
UUID可留空自动生成,也可手动填入合法 UUID

新增后程序会写入 config.yaml,并启动该猫棒的 ping 与 SSH 采集任务。

2. Docker/Portainer 部署和数据卷说明

Docker Hub 镜像

PON Stick Manager 不通过源码方式发布,部署时只需要从 Docker Hub 拉取镜像:

docker pull sky114514/pon-stick-manager:latest

Docker Compose

services:
  pon-stick-manager:
    image: sky114514/pon-stick-manager:latest
    container_name: pon-stick-manager
    restart: unless-stopped
    ports:
      - "5010:8765"
    environment:
      ONU_DATA_DIR: /data
      ONU_CONFIG: /data/config.yaml
      ONU_LOG_DIR: /data/logs
      ONU_HOST: 0.0.0.0
      ONU_PORT: 8765
    volumes:
      - /srv/docker/pon-stick-manager/data:/data

启动示例:

cd /srv/docker/pon-stick-manager
docker compose up -d

长期部署推荐目录

长期部署时,建议把配置、数据库和日志统一映射到宿主机的一个固定目录。例如宿主机目录为:

/srv/docker/pon-stick-manager/data

对应容器内目录固定为:

/data

最小可用 docker-compose.yml 示例:

services:
  pon-stick-manager:
    image: sky114514/pon-stick-manager:latest
    container_name: pon-stick-manager
    restart: unless-stopped
    ports:
      - "5010:8765"
    volumes:
      - /srv/docker/pon-stick-manager/data:/data
    environment:
      ONU_DATA_DIR: /data
      ONU_CONFIG: /data/config.yaml
      ONU_LOG_DIR: /data/logs
      ONU_HOST: 0.0.0.0
      ONU_PORT: 8765
      ONU_ENABLE_MOCK: "0"

启动前建议先创建并授权数据目录:

mkdir -p /srv/docker/pon-stick-manager/data/logs
chmod -R 0777 /srv/docker/pon-stick-manager/data

更新镜像时只需要重新拉取并重建容器,数据不会因为容器重建丢失:

cd /srv/docker/pon-stick-manager
docker compose pull
docker compose up -d

不要删除宿主机的 /srv/docker/pon-stick-manager/data,也不要在 Portainer 中勾选删除持久化数据卷。

常用环境变量:

变量默认值说明
PON_STICK_IMAGEsky114514/pon-stick-manager:latestDocker Hub 镜像地址
PON_STICK_PORT5010宿主机暴露端口,可按需修改
PON_STICK_DATA_DIR/srv/docker/pon-stick-manager/data宿主机数据目录
ONU_DATA_DIR/data容器内数据根目录
ONU_CONFIG/data/config.yaml配置文件路径
ONU_LOG_DIR/data/logs日志目录
ONU_HOST0.0.0.0Web 监听地址
ONU_PORT8765容器内 Web 端口
ONU_LOG_LEVELINFO日志级别
ONU_ENABLE_MOCK0是否允许 mock 猫棒配置,生产部署保持 0

Portainer 部署

  1. 在 Portainer 中进入目标环境,选择 Stacks。
  2. 新建 Stack,粘贴上面的 docker-compose.yml 内容。
  3. 在 Environment variables 中设置:
  1. 部署后访问 http://宿主机IP:5010/

数据卷内容

容器只需要持久化 /data。首次启动后通常会生成:

路径说明
/data/config.yaml用户配置文件;不存在时创建为空文件
/data/config.example.yaml示例配置,启动脚本从镜像复制
/data/state.json当前状态、设置、备注、UI 排序等
/data/history.sqlite3温度和收光历史数据库
/data/logs/app.log应用和 uvicorn 日志

请备份整个 /data 目录,尤其是 config.yamlstate.jsonhistory.sqlite3

3. 配置文件字段详细解释

示例配置:

server:
  host: 0.0.0.0
  port: 8765

storage:
  path: state.json

defaults:
  web_refresh_seconds: 15
  probe_interval_seconds: 30
  ping_interval_seconds: 10
  history_retention_hours: 168
  temperature_high_c: 75
  rx_power_low_db: -27
  restart_cycles: 3
  restart_threshold: 2
  ssh_timeout_seconds: 8
  script_timeout_seconds: 12
  auto_reboot_on_registration_failure: false
  static_sync_interval_hours: 12

sticks: []

server

字段类型默认值说明
host字符串0.0.0.0Web 服务监听地址。Docker 中通常保持 0.0.0.0
port整数8000,示例为 8765Web 服务监听端口。Docker 里容器内端口为 8765

运行时也可以用 ONU_HOSTONU_PORT 覆盖监听地址与端口。

storage

字段类型默认值说明
path字符串配置文件同目录下的 state.json状态文件路径。相对路径会以配置文件所在目录为基准

历史数据库固定使用状态文件同目录、同名目录下的 history.sqlite3

defaults

这些字段会作为初始设置写入 state.json,之后也可以在 Web 设置面板修改。

字段类型默认值说明
web_refresh_seconds正整数15前端自动刷新状态的间隔
probe_interval_seconds正整数30SSH 采集猫棒信息的间隔
ping_interval_seconds正整数10ping 检测间隔
history_retention_hours正整数168历史数据保留时长,单位小时
temperature_high_c数字75温度高阈值,大于等于该值记为异常
rx_power_low_db数字-27收光低阈值,小于等于该值记为异常
restart_cycles正整数3判断频繁重启的检测周期数
restart_threshold正整数2在窗口内达到该重启次数后记为重启异常
ssh_timeout_seconds正整数8SSH 连接、认证、执行单条写入命令的超时
script_timeout_seconds正整数12SSH 读取信息脚本的执行超时
auto_reboot_on_registration_failure布尔值代码默认 true,示例配置为 false注册失败时是否自动重启猫棒
static_sync_interval_hours正整数12静态信息完整同步间隔,例如 MAC、LOID、管理 IP 等

sticks

每个猫棒是一项列表元素:

sticks:
  - uuid: "11111111-1111-4111-8111-111111111111"
    name: Example PON Stick
    host: 192.168.70.1
    ping_host: 192.168.70.1
    ssh:
      host: 192.168.70.1
      port: 22
      username: root
      password: ""
字段类型必填说明
uuidUUID 字符串建议填写猫棒稳定 ID。为空或重复时,程序会自动生成并回写
id字符串旧版兼容字段。存在时会作为 legacy id,用于迁移旧状态
name字符串Web 展示名。为空时使用旧 iduuid
hostIPv4/主机名猫棒管理地址,也会作为默认 SSH 地址
ping_hostIPv4/主机名ping 检测地址,默认使用 host
mock布尔值是否使用 mock 猫棒。生产 Docker 默认不允许
ssh.hostIPv4/主机名SSH 连接地址,默认使用 host
ssh.port整数SSH 端口,默认 22
ssh.username字符串SSH 用户名,默认 root
ssh.password字符串SSH 密码。为空时程序会先尝试 none auth
ssh.key_filename字符串SSH 私钥路径。设置后 Paramiko 会使用该 key

手动修改 config.yaml 后,前端刷新或调用“同步配置”会热加载配置,新增、改名、改 IP 都会同步到运行中的监控任务。

4. Web 功能说明

首页卡片

每张猫棒卡片展示:

信息来源
名称、host、检测时间配置和状态文件
状态状态机结果
温度SSH 读取 SoC 温度
光衰SSH 通过 /tmp/cigcli 读取 Rx power
注册状态设备日志中的注册/去注册信息
IP、EPON 模式设备配置和运行信息
LOID、MAC、LOID Password设备配置文件或菜单命令

状态过滤支持“正常”和“异常”计数;搜索支持按名称、ID、host、状态、指标名、指标值、备注键值匹配。

设置面板

设置面板可调整:

保存后设置写入 state.json,运行中的监控循环会读取最新设置。

配置同步

“同步配置”会强制热加载 config.yaml,并对每台可采集猫棒执行一次完整静态信息同步。处于写入中、重启等待、ping 不可达等状态时,采集会被跳过并返回跳过原因。

编辑与写入

支持直接或批量写入:

功能说明
修改名称写入 config.yaml 和状态文件,不需要重启设备
编辑 LOID/MAC/LOID Password通过 SSH 写入设备配置
修改 IP写入设备管理 IP,同时更新 config.yaml 中的 hostping_hostssh.host
修改 EPON 模式支持 10G/1G10G/10G
修改登录密码通过交互式 passwd 修改 root 密码,并回写 config.yaml
重启设备通过 SSH 执行 reboot,然后进入重启状态跟踪

写入前会先检查:

批量写入成功后会触发重启,并标记静态信息需要重新同步。

备注和排序

每张卡片支持:

macloidloid password 等保留键会被视为配置字段,不能作为普通备注重复保存。

历史记录

温度和收光写入 history.sqlite3。点击指标旁的历史图标可查看:

当前实现会保存温度和收光,历史表中的 EPON 模式字段保留但不写入。

5. 状态机与异常处理简述

状态主要有:

状态含义
unknown初始状态,尚未有有效检测结果
normalping、SSH 和指标均正常
failed存在 ping、SSH、温度、收光、注册、写入或重启异常
rebooting已发起重启,正在等待设备恢复
unregistered注册失败且自动重启已被暂停

ping 与采集

SSH 和指标异常

SSH 连接、认证、命令超时或脚本错误会记录到 last_error,并写入异常项 ssh。温度大于等于阈值时产生 temperature 异常,收光小于等于阈值时产生 rx_power 异常。

注册状态会识别 Registered!O5normalok 为正常;De-registered!DeregisteredUnregisteredNot registeredNo registration 等会被视为注册失败。

重启流程

手动重启、批量配置写入、改 IP、改 EPON 模式、改登录密码或注册失败自动重启都会进入 rebooting

  1. 记录 requested_reboot_at
  2. 暂停普通 SSH 采集,等待 ping 恢复。
  3. ping 恢复后等待约 15 秒再允许 SSH 采集。
  4. SSH 连续失败 3 次后转为 failed
  5. SSH 采集成功后清除重启标记并回到正常或异常状态。
  6. 如果重启后 5 分钟仍无法 ping 通,标记 reboot_timeout

注册失败自动重启保护

启用 auto_reboot_on_registration_failure 后,注册失败会自动请求重启。为避免无限循环,1 小时内自动重启超过 20 次时会暂停自动流程,状态变为 unregistered,异常项包含 registration_blocked。Web 菜单中的“无法注册”操作可恢复该流程。

写入保护

写入设备时会设置 write_in_progress

6. 项目架构

PON Stick Manager 以单容器方式运行。容器内包含 Web 服务、后台检测任务、SSH 采集/写入逻辑和本地持久化存储。用户不需要源码,只需要拉取 Docker Hub 镜像并挂载 /data

运行时组件

Web UI
  │
  ▼
Web API
  │
  ├── 状态存储: /data/state.json + /data/history.sqlite3
  ├── 配置文件: /data/config.yaml
  ├── 日志文件: /data/logs/app.log
  ├── 后台检测:
  │     ├── ping 检测
  │     └── SSH 采集
  │
  └── 猫棒控制:
        ├── 读取温度、收光、注册状态、配置字段
        ├── 写入 LOID、MAC、LOID Password、IP、EPON 模式
        └── reboot / passwd

持久化边界

容器可以随时重建,真正需要保留的是宿主机映射目录:

/srv/docker/pon-stick-manager/data

只要这个目录没有被删除,重新拉取镜像、Recreate 容器或 Portainer 重新部署都不会丢失配置和历史数据。

7. 常见问题

页面打不开怎么办?

先确认容器正在运行,再检查端口映射。本文示例把宿主机 5010 映射到容器 8765,访问地址通常是:

http://宿主机IP:5010/

如果修改过 Compose 端口,检查 docker-compose.yml 中宿主机端口到容器 8765 的映射关系。

为什么新增猫棒后配置文件里出现 UUID?

程序使用 uuid 作为稳定 ID。启动或加载配置时,如果某个条目没有 UUID、UUID 重复或格式需要规范化,程序会自动生成或修正并写回 config.yaml

为什么 SSH 密码为空也会尝试连接?

如果 ssh.passwordssh.key_filename 都为空,程序会先尝试 SSH none auth。若设备不支持 none auth,再回退到密码/key 认证逻辑。

为什么设备不可达后不继续 SSH 采集?

连续 3 次 ping 失败后会暂停 SSH 采集,避免长时间阻塞和无意义的连接尝试。ping 恢复后采集会自动恢复。

为什么修改配置字段要求状态正常?

写入 LOID、MAC、IP、EPON 模式、登录密码等操作会改变设备配置,并且部分操作会重启设备。程序要求状态为 normal、没有异常、ping 可达且 SSH 复查成功,目的是降低在异常状态下写坏配置的风险。

修改 IP 后为什么 Web 上也会变?

修改 IP 会同时写入设备和 config.yaml,包括 hostping_hostssh.host。状态文件里的 host 也会更新,后续监控会使用新地址。

注册失败为什么会一直重启?

只有开启 auto_reboot_on_registration_failure 时才会自动重启。程序有保护:1 小时内自动重启超过 20 次会暂停流程,状态变为 unregistered。排查线路、LOID、MAC、EPON 模式等问题后,可以在 Web 菜单中恢复注册流程。

历史图表为什么没有数据?

历史只在采集到温度或收光时写入。如果 SSH 采集失败、设备处于重启等待、ping 不可达,或者相关字段缺失,就不会产生新的历史点。

如何备份和迁移?

备份 Docker 数据卷对应的宿主机目录即可。关键文件是:

迁移到新机器时,把数据目录挂载到新容器的 /data

可以把这个项目直接部署到 Cloudflare Pages 运行吗?

Cloudflare Pages 适合托管本文档这类静态 Markdown/站点。PON Stick Manager 本体需要 Python、FastAPI、后台 ping、SSH 和持久化数据卷,因此应部署在 Docker、Portainer、服务器或 NAS 上;Cloudflare Pages 可以作为说明书和下载入口。