update 2.0.0

This commit is contained in:
cppla
2026-07-10 16:53:46 +08:00
parent e4ca0558f7
commit 950c4d4a9a
4 changed files with 196 additions and 331 deletions
+196 -199
View File
@@ -1,24 +1,22 @@
# ServerStatus 中文版
ServerStatus 是一个轻量的服务器探针和云监控面板,支持多节点在线状态、资源占用、三网延迟、服务监测、SSL 证书检查、Watchdog 告警和 Web 配置管理。
ServerStatus 是一个轻量的服务器探针和云监控面板,支持多节点在线状态、资源占用、三网延迟、服务监测、SSL 证书检查、Watchdog 告警、HTTP API 和 Web 配置管理。
在线演示:https://tz.cloudcpp.com
[![Python Support](https://img.shields.io/badge/python-3.6%2B%20-blue.svg)](https://github.com/cppla/ServerStatus)
[![C++ Compiler](http://img.shields.io/badge/C++-GNU-blue.svg?style=flat&logo=cplusplus)](https://github.com/cppla/ServerStatus)
[![License](https://img.shields.io/badge/license-MIT-4EB1BA.svg?style=flat-square)](https://github.com/cppla/ServerStatus)
[![Version](https://img.shields.io/badge/Version-Build%201.1.9-red)](https://github.com/cppla/ServerStatus)
[![Go](https://img.shields.io/badge/Go-1.25%2B-00ADD8?logo=go&logoColor=white)](https://go.dev/)
[![CI](https://github.com/cppla/ServerStatus/actions/workflows/ci.yml/badge.svg)](https://github.com/cppla/ServerStatus/actions/workflows/ci.yml)
[![License](https://img.shields.io/badge/license-MIT-4EB1BA.svg)](LICENSE)
[![Version](https://img.shields.io/badge/Version-2.0.0-red)](https://github.com/cppla/ServerStatus)
![Latest Host Version](https://dl.cpp.la/Archive/serverstatus_1_1_9.webp)
`Watchdog 的 `interval` 是最小通知间隔,用于避免频繁报警,并不是探测间隔。`rule` 使用 Exprtk 表达式,当前窄字符解析对中文等 Unicode 字符不友好,规则中建议使用英文、数字和字段名。`
![ServerStatus WebUI](https://dl.cpp.la/Archive/serverstatus_2_0_0.webp)
## 一、服务端
```bash
# Docker Compose,本地构建加:--build
ADMIN_TOKEN='your-strong-token' docker compose -f docker-compose-server.yml up -d
ADMIN_TOKEN='your-strong-token' docker compose -f docker-compose-server.yml up -d --build
```
```bash
@@ -26,12 +24,12 @@ ADMIN_TOKEN='your-strong-token' docker compose -f docker-compose-server.yml up -
wget -qO ~/serverstatus-config.json \
--header='Accept: application/vnd.github.raw' \
'https://api.github.com/repos/cppla/ServerStatus/contents/server/config.json?ref=master'
mkdir -p ~/serverstatus-monthtraffic
mkdir -p ~/serverstatus-data
docker run -d --restart=always --name=serverstatus-server \
-e ADMIN_TOKEN='your-strong-token' \
-v ~/serverstatus-config.json:/ServerStatus/server/config.json \
-v ~/serverstatus-monthtraffic:/usr/share/nginx/html/json \
-v ~/serverstatus-config.json:/app/config/config.json \
-v ~/serverstatus-data:/app/data \
-p 8080:80 -p 35601:35601 \
cppla/serverstatus:server
```
@@ -39,16 +37,17 @@ docker run -d --restart=always --name=serverstatus-server \
启动后访问:
- WebUIhttp://127.0.0.1:8080/
- HTTP API 自检http://127.0.0.1:8080/api/health
- HTTP API 文档http://127.0.0.1:8080/api/schema
- HTTP 默认端口映射为`8080:80`,客户端连接端口为`35601``ADMIN_TOKEN` 可选:不设置时Web仅可查看监控数据,但web配置页无法修改。
- 健康检查http://127.0.0.1:8080/api/health
- API 描述http://127.0.0.1:8080/api/schema
- OpenAPI 3.1http://127.0.0.1:8080/api/openapi.json
- 客户端上报端口:`35601/tcp`,`ADMIN_TOKEN` 不设置时,监控页面仍可读取,管理 API 返回 `503`,WebUI 的“配置”页不能修改数据。
## 二、客户端
```bash
# Docker Compose,本地构建加:--build
SERVER=127.0.0.1 USER=s01 docker compose -f docker-compose-client.yml up -d --force-recreate
SERVER=127.0.0.1 USER=s01 PASSWORD=USER_DEFAULT_PASSWORD \
docker compose -f docker-compose-client.yml up -d --force-recreate
```
```bash
@@ -57,109 +56,129 @@ docker run -d --restart=always --name=serverstatus-client \
--network=host --pid=host \
-e SERVER=127.0.0.1 \
-e USER=s01 \
-e PASSWORD=USER_DEFAULT_PASSWORD \
cppla/serverstatus:client
```
```bash
# Shell Run
wget -qO client-linux.py --header='Accept: application/vnd.github.raw' 'https://api.github.com/repos/cppla/ServerStatus/contents/clients/client-linux.py?ref=master' && (nohup python3 client-linux.py SERVER=127.0.0.1 USER=s01 >/dev/null 2>&1 &)
wget -qO client-linux.py --header='Accept: application/vnd.github.raw' \
'https://api.github.com/repos/cppla/ServerStatus/contents/clients/client-linux.py?ref=master'
nohup python3 client-linux.py SERVER=127.0.0.1 USER=s01 PASSWORD=USER_DEFAULT_PASSWORD >/dev/null 2>&1 &
```
客户端环境变量和注意事项
`USER` 是常见的宿主机环境变量名。如果没有显式传递,Compose 可能会把系统里的 `$USER` 解析成本机用户名。推荐优先级:1. 运行命令显式传递 `USER=...`2. 用户修改 `docker-compose-client.yml` 里的 `USER` 默认值
`USER` 是常见的宿主机环境变量名。如果没有显式传递或传递方式错误,Compose 可能会把系统中的 `$USER` 解析成本机用户名,而不是默认的 `s01`。推荐优先级
1. 运行命令显式传递 `USER=s01`
2. 修改 `docker-compose-client.yml` 中的 `USER` 默认值
3. Docker 或系统环境中的 `USER`
| 变量 | 默认值 | 说明 |
| --- | --- | --- |
| `SERVER` | `127.0.0.1` | 服务端地址 |
| `SERVER` | `127.0.0.1` | Go 服务端地址 |
| `USER` | `s01` | 客户端用户名,必须匹配服务端配置 |
| `PORT` | `35601` | 服务端 sergate 端口 |
| `PORT` | `35601` | Agent TCP 上报端口 |
| `PASSWORD` | `USER_DEFAULT_PASSWORD` | 客户端密码,必须匹配服务端配置 |
| `INTERVAL` | `1` | 上报间隔 |
| `PROBEPORT` | `80` | 探测端口 |
| `PROBE_PROTOCOL_PREFER` | `ipv4` | 探测协议偏好 |
| `PING_PACKET_HISTORY_LEN` | `100` | Ping 历史长度 |
| `INTERVAL` | `1` | 状态上报间隔,单位秒 |
| `PROBEPORT` | `80` | 三网 TCP 探测端口 |
| `PROBE_PROTOCOL_PREFER` | `ipv4` | 探测协议偏好,可选 `ipv4``ipv6` |
| `PING_PACKET_HISTORY_LEN` | `100` | 丢包历史窗口 |
| `CU` | `cu.tz.cloudcpp.com` | 联通探测地址 |
| `CT` | `ct.tz.cloudcpp.com` | 电信探测地址 |
| `CM` | `cm.tz.cloudcpp.com` | 移动探测地址 |
| `CLIENT` | `psutil` | 客户端实现,可选 `psutil``linux` |
| `CLIENT` | `psutil` | 客户端实现,可选 `psutil``linux` |
## 服务端参数
Docker 镜像中的默认路径为:
| 环境变量 | 默认值 | 说明 |
| --- | --- | --- |
| `CONFIG_PATH` | `/app/config/config.json` | 主配置文件 |
| `STATS_PATH` | `/app/data/stats.json` | 月流量与状态持久化文件 |
| `WEB_DIR` | `/app/web` | WebUI 静态文件目录 |
| `HTTP_ADDR` | `:80` | WebUI 与 HTTP API 监听地址 |
| `AGENT_ADDR` | `:35601` | 客户端 TCP 上报监听地址 |
| `ADMIN_TOKEN` | 空 | 管理 API Bearer Token;为空时禁用管理接口 |
| `ADMIN_CORS_ORIGIN` | 空 | 可选的 API CORS Origin |
| `INSECURE_CALLBACK_TLS` | `false` | 是否允许 Watchdog/证书回调使用不可信 TLS 证书 |
| `VERBOSE` | `false` | 输出 Gin HTTP 请求日志 |
| `TZ` | `Asia/Shanghai` | 容器时区 |
对应命令行参数:
```text
--config, -c config.json 路径
--stats stats.json 路径
--web-dir, -d WebUI 目录
--http HTTP 监听地址
--agent Agent TCP 监听地址
--verbose, -v 详细请求日志
--version 输出构建版本
```
旧参数 `--bind/-b``--port/-p` 仍可用于设置 Agent TCP 监听地址。
## HTTP 管理 API
Docker 服务端镜像已内置 HTTP API,并通过 nginx 暴露在 Web 端口下。源码手动运行时需要单独启动 `server/manage_api.py`;如果要让 WebUI 的「配置」页可用,还需要把 `/api/` 反代到 `manage_api.py`。认证方式
管理接口使用 Bearer Token
```bash
Authorization: Bearer your-strong-token
```http
Authorization: Bearer <ADMIN_TOKEN>
```
无需认证的接口
无需认证:
| 方法 | 路径 | 用途 |
| --- | --- | --- |
| `GET` | `/api/health` | 进程、Agent TCP、版本和配置路径状态 |
| `GET` | `/api/schema` | 机器可读的端点与配置集合描述 |
| `GET` | `/api/openapi.json` | 可供 AI Agent 直接导入的 OpenAPI 3.1 文档 |
| `GET` | `/json/stats.json` | WebUI 使用的实时状态快照 |
需要认证:
| 方法 | 路径 | 用途 |
| --- | --- | --- |
| `GET/PUT` | `/api/config` | 读取或整体替换配置 |
| `GET/POST` | `/api/servers` | 查询或新增节点 |
| `PUT/DELETE` | `/api/servers/{username}` | 修改或删除节点 |
| `POST` | `/api/servers/{username}/reset-traffic` | 将当前流量设为本月基线 |
| `GET/POST` | `/api/monitors` | 查询或新增服务监测 |
| `PUT/DELETE` | `/api/monitors/{index-or-name}` | 修改或删除服务监测 |
| `GET/POST` | `/api/sslcerts` | 查询或新增证书监测 |
| `PUT/DELETE` | `/api/sslcerts/{index-or-name}` | 修改或删除证书监测 |
| `GET/POST` | `/api/watchdog` | 查询或新增 Watchdog |
| `PUT/DELETE` | `/api/watchdog/{index-or-name}` | 修改或删除 Watchdog |
| `POST` | `/api/reload` | 从磁盘重新读取配置 |
| `POST` | `/api/restart` | 在进程内重启采集运行时 |
配置修改采用“校验 → 备份 → 持久化 → 原子切换”的顺序。成功后现有 Agent 连接会被关闭,Python 客户端约 3 秒后自动重连并获取新的 `monitors``/api/restart` 不退出 Go 进程,因此 Docker 和手动运行方式具有一致语义。
常用调用:
```bash
TOKEN='请替换为 ADMIN_TOKEN'
curl http://127.0.0.1:8080/api/health
curl http://127.0.0.1:8080/api/schema
```
读取完整配置:
```bash
curl -H 'Authorization: Bearer your-strong-token' \
curl -H "Authorization: Bearer ${TOKEN}" \
http://127.0.0.1:8080/api/config
```
节点 CRUD
```bash
curl -X POST http://127.0.0.1:8080/api/servers \
-H 'Authorization: Bearer your-strong-token' \
-H "Authorization: Bearer ${TOKEN}" \
-H 'Content-Type: application/json' \
-d '{"username":"s05","name":"node5","type":"kvm","host":"host5","location":"SG","password":"USER_DEFAULT_PASSWORD","monthstart":1}'
-d '{"username":"s05","name":"node5","type":"kvm","host":"host5","location":"SG","password":"change-me","monthstart":1}'
curl -X PUT http://127.0.0.1:8080/api/servers/s05 \
-H 'Authorization: Bearer your-strong-token' \
-H 'Content-Type: application/json' \
-d '{"username":"s05","name":"node5-new","type":"kvm","host":"host5","location":"SG","password":"USER_DEFAULT_PASSWORD","monthstart":1}'
curl -X DELETE -H 'Authorization: Bearer your-strong-token' \
curl -X DELETE \
-H "Authorization: Bearer ${TOKEN}" \
http://127.0.0.1:8080/api/servers/s05
```
`monitors``sslcerts``watchdog` 也支持细粒度 CRUD。更新和删除可以用数字 `index`;如果 `name` 唯一,也可以用 URL 编码后的 `name`
```bash
curl -X POST http://127.0.0.1:8080/api/monitors \
-H 'Authorization: Bearer your-strong-token' \
-H 'Content-Type: application/json' \
-d '{"name":"demo","host":"https://example.com","type":"https","interval":600}'
curl -X PUT http://127.0.0.1:8080/api/sslcerts/0 \
-H 'Authorization: Bearer your-strong-token' \
-H 'Content-Type: application/json' \
-d '{"name":"example","domain":"https://example.com","port":443,"interval":7200,"callback":"https://yourSMSurl"}'
curl -X DELETE -H 'Authorization: Bearer your-strong-token' \
http://127.0.0.1:8080/api/watchdog/0
```
重载配置或重启 `sergate`
```bash
curl -X POST -H 'Authorization: Bearer your-strong-token' \
http://127.0.0.1:8080/api/reload
curl -X POST -H 'Authorization: Bearer your-strong-token' \
http://127.0.0.1:8080/api/restart
```
完整端点以 `/api/schema` 输出为准。
请求体最大为 `1 MiB`。AI Agent 可直接导入 `/api/openapi.json`;轻量客户端也可以先读取 `/api/schema`,再根据返回的集合字段调用 CRUD 接口
## 配置文件
配置文件默认路径:
- Docker 服务端:`/ServerStatus/server/config.json`
- 源码运行:`server/config.json`,或通过 `--config` 指定
基础示例:
```json
{
"servers": [
@@ -170,7 +189,8 @@ curl -X POST -H 'Authorization: Bearer your-strong-token' \
"host": "host1",
"location": "CN",
"password": "USER_DEFAULT_PASSWORD",
"monthstart": 1
"monthstart": 1,
"disabled": false
}
],
"monitors": [
@@ -187,7 +207,7 @@ curl -X POST -H 'Authorization: Bearer your-strong-token' \
"domain": "https://example.com",
"port": 443,
"interval": 7200,
"callback": "https://yourSMSurl"
"callback": "https://example.net/push?message="
}
],
"watchdog": [
@@ -195,147 +215,124 @@ curl -X POST -H 'Authorization: Bearer your-strong-token' \
"name": "offline warning",
"rule": "online4=0&online6=0",
"interval": 600,
"callback": "https://yourSMSurl"
},
{
"name": "cpu high warning",
"rule": "cpu>90&load_1>5&username!='s01'",
"interval": 600,
"callback": "https://yourSMSurl"
"callback": "https://example.net/push?message="
}
]
}
```
常见 Watchdog 回调
约束
- `servers.username` 必须唯一。
- `monthstart` 自动限制在 `1-28`
- `port` 自动限制在 `1-65535`
- `interval` 最小为 1 秒;Watchdog 中表示通知冷却时间,不是客户端采集间隔。
- 配置写入前会创建 `config.json.bak-*`,最多保留 10 份。
- Docker 单文件 bind mount 无法被 `rename` 覆盖时,服务端会在完成备份后安全地写回原 inode。
使用 Docker 单文件挂载时,配置备份位于容器 `/app/config` 的可写层;如需长期保留历史版本,建议同时在宿主机备份 `server/config.json`
### Watchdog 表达式
`rule` 由 Go `expr` 引擎执行,并兼容旧版 Exprtk 的常用写法。Go 服务会把字符串外的单个操作符自动转换:
```text
Telegram: https://api.telegram.org/bot你的密钥/sendMessage?parse_mode=HTML&disable_web_page_preview=true&chat_id=你的标识&text=
Server酱: https://sctapi.ftqq.com/你的密钥.send?title=ServerStatus&desp=
PushDeer: https://api2.pushdeer.com/message/push?pushkey=你的密钥&text=
HttpBasicAuth: https://用户名:密码@你的域名/api/push?message=
& -> &&
| -> ||
= -> ==
```
例如以下两种写法等价:
```text
cpu>90&load_1>5&username!='s01'
cpu>90 && load_1>5 && username!='s01'
```
字符串值支持中文、Emoji 和其他 Unicode 字符,例如:
```text
username='节点一号'&name='上海节点'&location='中国 🇨🇳'&type='云主机'
```
字段名必须使用系统定义的英文名称。可用字段包括:`username``name``type``host``location``load_1``load_5``load_15``cpu``memory_total``memory_used``swap_total``swap_used``hdd_total``hdd_used``network_rx``network_tx``network_in``network_out``last_network_in``last_network_out``ping_10010``ping_189``ping_10086``time_10010``time_189``time_10086``tcp_count``udp_count``process_count``thread_count``io_read``io_write``online4``online6`
客户端断开 25 秒后仍未重连,服务端才计算离线规则,避免短暂网络波动触发告警。每个节点、每条规则分别记录冷却时间。
### SSL 证书
证书检查使用 Go `crypto/tls`,不再调用外部 `openssl`。服务端记录到期时间、剩余天数和域名匹配状态,并保留原来的 7/3/1 天通知档位与冷却时间。
回调默认校验 HTTPS 证书。仅在必须兼容自签名回调服务时设置:
```bash
INSECURE_CALLBACK_TLS=true
```
## 源码编译和运行
服务端依赖
需要 Go `1.25` 或更高版本
```bash
# Debian/Ubuntu
apt-get -y install gcc g++ make libcurl4-openssl-dev python3 nginx openssl
# CentOS/RedHat
yum -y install gcc gcc-c++ make libcurl-devel python3 nginx openssl
cd server
go mod download
go test ./...
go build -trimpath -ldflags='-s -w' -o serverstatus .
```
编译并运行 `sergate`
`server/` 目录启动
```bash
cd ServerStatus/server
make
mkdir -p ../web/json
./sergate --config=config.json --web-dir=../web &
echo $! > /tmp/serverstatus-sergate.pid
ADMIN_TOKEN='请替换为高强度随机字符串' \
./serverstatus \
--config=config.json \
--stats=../web/json/stats.json \
--web-dir=../web \
--http=:8080 \
--agent=:35601
```
如果只需要 HTTP API,可以再启动 `manage_api.py`
访问 http://127.0.0.1:8080/。发送 `SIGHUP` 可以重新读取配置
```bash
cd ServerStatus/server
ADMIN_TOKEN='your-strong-token' \
CONFIG_PATH="$PWD/config.json" \
SERGATE_PID_FILE=/tmp/serverstatus-sergate.pid \
ADMIN_API_BIND=127.0.0.1 \
ADMIN_API_PORT=35602 \
python3 manage_api.py
kill -HUP "$(pgrep -x serverstatus)"
```
源码方式直连 API
Systemd 示例位于 `service/status-server.service`。一键脚本 `status.sh` 也已切换到 Go 构建,但 Docker 仍是推荐部署方式。
## 构建和测试
```bash
curl http://127.0.0.1:35602/api/health
curl -H 'Authorization: Bearer your-strong-token' \
http://127.0.0.1:35602/api/config
```
# Go 单元、协议、API、TLS 和回调测试
cd server
go test ./...
go test -race ./...
go vet ./...
如果要通过 WebUI 使用「配置」页,需要 nginx 同时提供静态文件并反代 `/api/`。示例配置:
```nginx
server {
listen 8080;
server_name _;
root /path/to/ServerStatus/web;
index index.html;
location / {
try_files $uri $uri/ =404;
}
location /json/ {
add_header Cache-Control "no-store";
try_files $uri =404;
}
location /api/ {
proxy_pass http://127.0.0.1:35602;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 30s;
}
}
```
启动失败时优先检查端口占用:`35601``sergate` 客户端上报端口,`35602` 是源码方式的管理 API 端口,`8080` 是上面示例的 Web 端口。源码手动运行没有 Docker 入口脚本守护;调用 `/api/restart` 会向 `sergate` 发送 `SIGTERM`,需要你用 systemd、supervisor 或 shell 循环自行拉起。
## 客户端源码运行
`client-linux.py`
```bash
wget -qO client-linux.py \
--header='Accept: application/vnd.github.raw' \
'https://api.github.com/repos/cppla/ServerStatus/contents/clients/client-linux.py?ref=master'
nohup python3 client-linux.py SERVER=127.0.0.1 USER=s01 PASSWORD=USER_DEFAULT_PASSWORD \
>/dev/null 2>&1 &
```
`client-psutil.py`
```bash
# Debian/Ubuntu
apt -y install python3-psutil
# CentOS/RedHat
yum -y install python3-pip gcc python3-devel
pip3 install psutil
python3 clients/client-psutil.py SERVER=127.0.0.1 USER=s01
```
后台运行与开机启动:
```bash
nohup python3 client-linux.py SERVER=127.0.0.1 USER=s01 &
# crontab -e
@reboot /usr/bin/python3 /path/to/client-linux.py SERVER=127.0.0.1 USER=s01
```
## 本地构建镜像
```bash
# Docker 镜像
cd ..
docker build -f Dockerfile.server -t cppla/serverstatus:server .
docker build -f Dockerfile.client -t cppla/serverstatus:client .
# Compose 配置
docker compose -f docker-compose-server.yml config
docker compose -f docker-compose-client.yml config
```
## Make Better
CI 还会检查 Go 格式、Python 客户端、Shell 脚本、WebUI JavaScript、主服务/客户端/Telegram Compose 文件和两个 Docker 镜像。
* BotoXhttps://github.com/BotoX/ServerStatus
* mojedahttps://github.com/mojeda
* mojeda's ServerStatushttps://github.com/mojeda/ServerStatus
* BlueVM's projecthttp://www.lowendtalk.com/discussion/comment/169690#Comment_169690
## 从旧服务端迁移
1. 备份原来的 `config.json``web/json/stats.json`
2. 原配置结构和客户端账号无需转换。
3. Docker 挂载目标改为 `/app/config/config.json``/app/data`
4. 删除旧的 nginx、`manage_api.py``sergate` 启动或监督配置。
5. 启动 Go 服务端后检查 `/api/health`,再观察客户端自动重连。
`stats.json` 会按节点的 `name/type/host/location` 恢复月流量基线。修改这些身份字段会被视为新节点。
## 致谢
- BotoXhttps://github.com/BotoX/ServerStatus
- mojedahttps://github.com/mojeda/ServerStatus