Files

229 lines
8.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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`。如果仓库本身已经放在 `/opt/server-monitor`,脚本会跳过自我复制,可直接重复运行。
```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/<iface>/speed` |
| Top 进程 | `/proc/<pid>/stat`、`/proc/<pid>/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 修改端口。