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_IMAGE | sky114514/pon-stick-manager:latest | Docker Hub 镜像地址 |
PON_STICK_PORT | 5010 | 宿主机暴露端口,可按需修改 |
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_HOST | 0.0.0.0 | Web 监听地址 |
ONU_PORT | 8765 | 容器内 Web 端口 |
ONU_LOG_LEVEL | INFO | 日志级别 |
ONU_ENABLE_MOCK | 0 | 是否允许 mock 猫棒配置,生产部署保持 0 |
Portainer 部署
- 在 Portainer 中进入目标环境,选择 Stacks。
- 新建 Stack,粘贴上面的
docker-compose.yml内容。 - 在 Environment variables 中设置:
PON_STICK_IMAGE:sky114514/pon-stick-manager:latestPON_STICK_PORT: Web 端口,例如5010PON_STICK_DATA_DIR: 持久化目录或命名卷,例如/srv/docker/pon-stick-manager/data
- 部署后访问
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.yaml、state.json 和 history.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.0 | Web 服务监听地址。Docker 中通常保持 0.0.0.0 |
port | 整数 | 8000,示例为 8765 | Web 服务监听端口。Docker 里容器内端口为 8765 |
运行时也可以用 ONU_HOST 和 ONU_PORT 覆盖监听地址与端口。
storage
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
path | 字符串 | 配置文件同目录下的 state.json | 状态文件路径。相对路径会以配置文件所在目录为基准 |
历史数据库固定使用状态文件同目录、同名目录下的 history.sqlite3。
defaults
这些字段会作为初始设置写入 state.json,之后也可以在 Web 设置面板修改。
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
web_refresh_seconds | 正整数 | 15 | 前端自动刷新状态的间隔 |
probe_interval_seconds | 正整数 | 30 | SSH 采集猫棒信息的间隔 |
ping_interval_seconds | 正整数 | 10 | ping 检测间隔 |
history_retention_hours | 正整数 | 168 | 历史数据保留时长,单位小时 |
temperature_high_c | 数字 | 75 | 温度高阈值,大于等于该值记为异常 |
rx_power_low_db | 数字 | -27 | 收光低阈值,小于等于该值记为异常 |
restart_cycles | 正整数 | 3 | 判断频繁重启的检测周期数 |
restart_threshold | 正整数 | 2 | 在窗口内达到该重启次数后记为重启异常 |
ssh_timeout_seconds | 正整数 | 8 | SSH 连接、认证、执行单条写入命令的超时 |
script_timeout_seconds | 正整数 | 12 | SSH 读取信息脚本的执行超时 |
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: ""
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
uuid | UUID 字符串 | 建议填写 | 猫棒稳定 ID。为空或重复时,程序会自动生成并回写 |
id | 字符串 | 否 | 旧版兼容字段。存在时会作为 legacy id,用于迁移旧状态 |
name | 字符串 | 否 | Web 展示名。为空时使用旧 id 或 uuid |
host | IPv4/主机名 | 是 | 猫棒管理地址,也会作为默认 SSH 地址 |
ping_host | IPv4/主机名 | 否 | ping 检测地址,默认使用 host |
mock | 布尔值 | 否 | 是否使用 mock 猫棒。生产 Docker 默认不允许 |
ssh.host | IPv4/主机名 | 否 | 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、状态、指标名、指标值、备注键值匹配。
设置面板
设置面板可调整:
- 页面刷新间隔
- 状态检测间隔
- ping 间隔
- 温度阈值
- 收光低阈值
- 连续检测周期和重启次数阈值
- 注册失败后自动重启
- 配置同步间隔
- 历史保留时长
保存后设置写入 state.json,运行中的监控循环会读取最新设置。
配置同步
“同步配置”会强制热加载 config.yaml,并对每台可采集猫棒执行一次完整静态信息同步。处于写入中、重启等待、ping 不可达等状态时,采集会被跳过并返回跳过原因。
编辑与写入
支持直接或批量写入:
| 功能 | 说明 |
|---|---|
| 修改名称 | 写入 config.yaml 和状态文件,不需要重启设备 |
| 编辑 LOID/MAC/LOID Password | 通过 SSH 写入设备配置 |
| 修改 IP | 写入设备管理 IP,同时更新 config.yaml 中的 host、ping_host 和 ssh.host |
| 修改 EPON 模式 | 支持 10G/1G 与 10G/10G |
| 修改登录密码 | 通过交互式 passwd 修改 root 密码,并回写 config.yaml |
| 重启设备 | 通过 SSH 执行 reboot,然后进入重启状态跟踪 |
写入前会先检查:
- 当前状态必须为
normal - 当前没有异常项
- 没有其他写入操作正在进行
- ping 可达
- SSH 现场复查成功
批量写入成功后会触发重启,并标记静态信息需要重新同步。
备注和排序
每张卡片支持:
- 添加用户自定义键值备注
- 添加或修改 20 字以内的短备注
- 拖拽调整 LOID、MAC、LOID Password 和用户备注的显示顺序
- 拖拽删除用户备注
mac、loid、loid password 等保留键会被视为配置字段,不能作为普通备注重复保存。
历史记录
温度和收光写入 history.sqlite3。点击指标旁的历史图标可查看:
- 折线图
- 原始值表格
- 1 小时、6 小时、24 小时、72 小时或全部数据
当前实现会保存温度和收光,历史表中的 EPON 模式字段保留但不写入。
5. 状态机与异常处理简述
状态主要有:
| 状态 | 含义 |
|---|---|
unknown | 初始状态,尚未有有效检测结果 |
normal | ping、SSH 和指标均正常 |
failed | 存在 ping、SSH、温度、收光、注册、写入或重启异常 |
rebooting | 已发起重启,正在等待设备恢复 |
unregistered | 注册失败且自动重启已被暂停 |
ping 与采集
- 连续 3 次 ping 失败后,状态变为
failed,异常项为ping unreachable。 - ping 失败达到阈值后会暂停 SSH 采集,避免对不可达设备继续执行命令。
- ping 恢复后会清除 ping 异常,并恢复采集。
SSH 和指标异常
SSH 连接、认证、命令超时或脚本错误会记录到 last_error,并写入异常项 ssh。温度大于等于阈值时产生 temperature 异常,收光小于等于阈值时产生 rx_power 异常。
注册状态会识别 Registered!、O5、normal、ok 为正常;De-registered!、Deregistered、Unregistered、Not registered、No registration 等会被视为注册失败。
重启流程
手动重启、批量配置写入、改 IP、改 EPON 模式、改登录密码或注册失败自动重启都会进入 rebooting:
- 记录
requested_reboot_at。 - 暂停普通 SSH 采集,等待 ping 恢复。
- ping 恢复后等待约 15 秒再允许 SSH 采集。
- SSH 连续失败 3 次后转为
failed。 - SSH 采集成功后清除重启标记并回到正常或异常状态。
- 如果重启后 5 分钟仍无法 ping 通,标记
reboot_timeout。
注册失败自动重启保护
启用 auto_reboot_on_registration_failure 后,注册失败会自动请求重启。为避免无限循环,1 小时内自动重启超过 20 次时会暂停自动流程,状态变为 unregistered,异常项包含 registration_blocked。Web 菜单中的“无法注册”操作可恢复该流程。
写入保护
写入设备时会设置 write_in_progress:
- 写入期间跳过后台采集。
- 第二个写入请求会返回冲突。
- 写入失败会记录
ssh_write异常。 - 写入结束后无论成功失败都会清除写入标记。
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.password 和 ssh.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,包括 host、ping_host、ssh.host。状态文件里的 host 也会更新,后续监控会使用新地址。
注册失败为什么会一直重启?
只有开启 auto_reboot_on_registration_failure 时才会自动重启。程序有保护:1 小时内自动重启超过 20 次会暂停流程,状态变为 unregistered。排查线路、LOID、MAC、EPON 模式等问题后,可以在 Web 菜单中恢复注册流程。
历史图表为什么没有数据?
历史只在采集到温度或收光时写入。如果 SSH 采集失败、设备处于重启等待、ping 不可达,或者相关字段缺失,就不会产生新的历史点。
如何备份和迁移?
备份 Docker 数据卷对应的宿主机目录即可。关键文件是:
config.yamlstate.jsonhistory.sqlite3logs/app.log,如需保留日志
迁移到新机器时,把数据目录挂载到新容器的 /data。
可以把这个项目直接部署到 Cloudflare Pages 运行吗?
Cloudflare Pages 适合托管本文档这类静态 Markdown/站点。PON Stick Manager 本体需要 Python、FastAPI、后台 ping、SSH 和持久化数据卷,因此应部署在 Docker、Portainer、服务器或 NAS 上;Cloudflare Pages 可以作为说明书和下载入口。