# Server Monitor Linux 服务器监控展示牌。监听 `0.0.0.0`,通过 `/proc`、`/sys` 和 `statvfs` 采集系统指标,在 **1024×768** 优化的面板上自动滚动展示,并随屏幕尺寸等比缩放。 ![面板预览](docs/preview.png) ## 特性 - **零第三方依赖**:只需要 Python 3.8+,不需要 pip 安装任何包。 - **完整指标**:CPU 使用率 / 每核心 / user-system-iowait-steal 拆分、内存与 Swap、LOAD 1/5/15、Uptime、文件系统、磁盘 I/O、网络速率与累计流量、Top 进程、温度、频率。 - **展示牌设计**:1024×768 基准,5 个页面自动轮播;顶部固定主机名、当前时间、时区、Uptime、IP;底部状态跑马灯。 - **实时数据**:默认每秒采样一次;SSE 推送,断线后自动回退到 HTTP 轮询。 - **无需前端构建**:原生 HTML/CSS/Canvas,无 CDN、无外网字体或图标,内网离线可用。 - **可选 Basic 认证**;systemd 服务使用 `DynamicUser` 降权运行,只读访问系统数据。 - **内置演示模式**:在没有 Linux `/proc` 的机器上也能预览完整面板。 ## 面板 | 页面 | 内容 | | --- | --- | | 01 系统概览 | CPU / 内存 / LOAD / 文件系统 / 网络速率,节点信息 | | 02 处理器与负载 | 大环图、16 核心网格、CPU 拆分、CPU Top 进程、负载趋势 | | 03 内存 | 内存构成、Swap、60 秒趋势、内存 Top 进程 | | 04 存储 | 文件系统用量汇总、块设备 I/O、I/O 60 秒趋势 | | 05 网络 | 总吞吐、RX/TX 趋势、每网卡速率/累计/错误/链路速率 | 默认每页轮播 10 秒;任意页面都会保留主机名、服务器时间、时区和 Uptime。底部的 STATUS 跑马灯会滚动显示阈值告警与实时摘要。 ## 快速开始 ### Linux(实时模式) ```bash # 需要 Python 3.8+ python3 monitor.py --bind 0.0.0.0 --port 8787 ``` 浏览器打开 `http://<服务器IP>:8787/`。 ### 任意系统(演示模式) ```bash python3 monitor.py --demo --bind 127.0.0.1 --port 8787 ``` 演示模式不读取本机 `/proc`,使用模拟的 16 核服务器数据,适合做 UI 预览、截图和无 Linux 环境下的开发。 ### 一次性输出 JSON ```bash python3 monitor.py --once --demo python3 monitor.py --once # Linux 上采样两次后输出实时快照 ``` ## 安装为 systemd 服务 ```bash chmod +x install.sh sudo ./install.sh ``` 脚本会把程序安装到 `/opt/server-monitor`,安装 `server-monitor.service`,并立即启动。默认监听 `0.0.0.0:8787`。 ```bash systemctl status server-monitor --no-pager journalctl -u server-monitor -f ``` 如需启用 Basic 认证: ```bash sudo vi /etc/server-monitor.env # 写入: # SERVER_MONITOR_AUTH=admin:换成一个强密码 sudo systemctl restart server-monitor ``` 密码中不能包含换行;用户名和密码用第一个冒号分隔,密码本身可以包含冒号。修改端口推荐使用 systemd drop-in: ```bash sudo systemctl edit server-monitor ``` ```ini [Service] ExecStart= ExecStart=/usr/bin/python3 /opt/server-monitor/monitor.py --bind 0.0.0.0 --port 9000 ``` 然后执行 `sudo systemctl daemon-reload && sudo systemctl restart server-monitor`。 ## 命令行参数 | 参数 | 默认值 | 说明 | | --- | --- | --- | | `--bind` | `0.0.0.0` | 监听地址。只给本机看可用 `127.0.0.1` | | `--port` | `8787` | 监听端口 | | `--interval` | `1.0` | 采样间隔(秒,最小 0.2) | | `--demo` | 关闭 | 使用演示数据,可在 Windows/macOS 运行 | | `--once` | 关闭 | 输出一次 JSON 快照后退出 | | `--auth USER:PASSWORD` | 无 | 启用 HTTP Basic 认证 | | `--web-dir DIR` | 内置 `web/` | 前端静态文件目录 | | `--verbose` | 关闭 | 输出 HTTP 访问日志 | | `--version` | — | 显示版本 | 环境变量 `SERVER_MONITOR_AUTH` 等价于 `--auth`,systemd 安装方式使用该变量。 ## URL 参数与快捷键 | 参数 | 示例 | 说明 | | --- | --- | --- | | `page` | `?page=3` | 初始显示第 1–5 页 | | `rotate` | `?rotate=15` | 每页停留秒数(4–120,默认 10) | | `paused` | `?paused=1` | 打开时暂停自动轮播 | 快捷键: - `Space`:暂停 / 继续轮播 - `←` / `→`:上一页 / 下一页 - `1`–`5`:直接跳转页面 - `F`:全屏 适合做值守大屏或 kiosk。页面会按 `min(视口宽/1024, 视口高/768)` 等比缩放,4:3 屏幕刚好铺满,16:9 屏幕居中留边且不会拉伸。 ## HTTP 接口 | 路径 | 说明 | | --- | --- | | `/` | 展示牌 | | `/api/snapshot` | 当前完整 JSON 快照(含 60 点历史) | | `/api/stream` | SSE 实时推送,每个采样点一条 `data:` | | `/healthz` | 健康检查,返回 `{ok, samples, interval, uptime_seconds}` | `/healthz` 不要求认证;其余路径在配置认证后需要 Basic 凭据。接口只读,不接受任何写入或控制指令。 ## 指标来源 | 指标 | 来源 | | --- | --- | | CPU 总量 / 每核心 / 拆分 | `/proc/stat` | | CPU 型号 / 物理核心 | `/proc/cpuinfo` | | CPU 频率 | `cpufreq/scaling_cur_freq`,回退 `/proc/cpuinfo` | | CPU 温度 | `/sys/class/thermal/thermal_zone*`,回退 `hwmon` | | 内存 / Swap | `/proc/meminfo` | | LOAD / 运行线程 | `/proc/loadavg` | | Uptime / 启动时间 | `/proc/uptime` | | 文件系统 | `/proc/mounts` + `statvfs(2)` | | 磁盘 I/O | `/proc/diskstats` + `/sys/class/block`(过滤分区) | | 网络速率 / 累计 | `/proc/net/dev` | | 网卡 IP / 默认路由 | `ip -j addr`(可选)、`/proc/net/route`、UDP 路由探测 | | 网卡链路速率 | `/sys/class/net//speed` | | Top 进程 | `/proc//stat`、`/proc//cmdline` | | 主机信息 | `/etc/os-release`、`uname(2)`、`gethostname(2)` | 说明: - 网络汇总默认排除 `lo`、veth、docker、br-、virbr、cni 等虚拟接口,避免容器主机重复计数;网卡明细仍会列出主要接口。 - 磁盘 I/O 已过滤分区设备,避免整盘和分区重复统计;容器内的 `overlay` 根文件系统会按实际挂载显示。 - 进程 CPU 百分比是按“全部逻辑核心”归一化的,可超过 100%(例如 4 核机器上单进程跑满 4 核约等于 400%)。 - 所有采样都在一个后台线程完成,多个浏览器同时打开也只产生一份系统采样。 ## 安全与部署建议 - 默认监听所有网卡,但**无认证**。部署到公网前请启用 `SERVER_MONITOR_AUTH`,并用防火墙限制来源,或放在带 TLS 的反向代理后面。 - 程序以只读方式访问 `/proc`、`/sys` 和挂载点;systemd 单元使用 `DynamicUser=yes`、`ProtectSystem=strict`、空 capability 集。 - 如果服务器使用了 `hidepid=2`,普通用户可能看不到其他用户的进程,进程 Top 会相应减少;这是内核权限策略,不是面板故障。 - 如果把 `/home` 下的挂载点也纳入监控,请确认 systemd 的 `ProtectHome=read-only` 不会改变你的预期;可按需删除该行。 - Basic 认证只保护凭据传输前的内容,公网使用务必加 HTTPS。 ## 开发与测试 ```bash python3 -m unittest discover -s tests -v node --check web/app.js ``` 测试使用临时伪造的 `/proc` 数据验证 CPU 差值、内存、网络速率、磁盘 I/O 和演示快照,不会读取或修改真实服务器数据。 目录结构: ```text monitor.py CLI 入口 servermon/metrics.py /proc /sys 解析与快照 servermon/demo.py 演示数据源 servermon/service.py 后台采样、历史环形缓冲、SSE 广播 servermon/web.py HTTP / SSE / 静态文件 / Basic Auth web/ 原生前端(HTML/CSS/Canvas) deploy/server-monitor.service install.sh tests/test_metrics.py ``` ## 卸载 ```bash sudo systemctl disable --now server-monitor sudo rm -f /etc/systemd/system/server-monitor.service sudo systemctl daemon-reload sudo rm -rf /opt/server-monitor sudo rm -f /etc/server-monitor.env ``` ## 故障排查 **页面一直显示“连接中”或空白** - 确认访问的是 `http://IP:8787/`,且防火墙放行端口。 - 查看 `journalctl -u server-monitor -f`。 - 非 Linux 上启动实时模式会直接报错,请加 `--demo` 或把程序部署到 Linux。 **中文显示成方框** 目标浏览器缺少中文字体。Debian/Ubuntu 可安装 `fonts-noto-cjk`,或在浏览器端使用包含中文字体的系统。 **磁盘列表为空** 检查挂载的文件系统类型是否在 `REAL_FS_TYPES` 中;容器内的特殊文件系统可能被有意过滤。可以先用 `findmnt` 确认挂载类型。 **进程 Top 为空** 检查 `/proc` 是否被 `hidepid` 限制,以及 systemd 的 `DynamicUser` 是否有权限读取目标进程的 `stat`。 **端口被占用** ```bash ss -lntp | grep 8787 ``` 改用 `--port` 或 systemd drop-in 修改端口。