服务器性能诊断工具集,自动生成标准 Markdown 分析报告。
支持两种使用方式:
- 统一入口
server-scan:子命令风格,适合 Agent 调用 - 独立脚本:直接执行各
.sh脚本
| 脚本 | 子命令 | 功能 | 适用场景 |
|---|---|---|---|
core/sys_overview.sh |
overview |
系统瓶颈总览 | 快速扫描 CPU / 内存 / 磁盘 / 网络 |
core/cpu_mem_analyzer.sh |
cpu-mem |
CPU / 内存深度分析 | 排查负载高、内存不足、OOM 风险 |
core/disk_analyzer.sh |
disk |
磁盘空间 / IO / 健康分析 | 排查磁盘满、IO 瓶颈、SMART 预警 |
core/network_analyzer.sh |
network |
网络专项排查 | 接口、连通性、连接数、DNS |
core/security_scanner.sh |
security |
杀毒软件 / 主机安全防护检测 | 排查服务器上是否部署杀毒 / HIDS / EDR |
core/cron_setup.sh |
cron |
定时任务管理 | 交互式配置 crontab 定时巡检 |
server-scan/
├── server-scan # 统一入口(根目录下唯一的可执行入口)
├── core/ # 各专项诊断脚本
│ ├── sys_overview.sh
│ ├── cpu_mem_analyzer.sh
│ ├── disk_analyzer.sh
│ ├── network_analyzer.sh
│ ├── security_scanner.sh
│ └── cron_setup.sh # 定时任务管理
├── lib/ # 共享库与语言包
│ ├── common.sh # 通用函数(进度、报告、超时、配置加载)
│ ├── cli.sh # 统一 CLI 参数解析
│ ├── alerts.sh # 结构化告警收集与 JSON 输出
│ ├── notify.sh # 通知推送(飞书)
│ └── i18n/ # 中英文语言包
├── output/ # 扫描产物(报告 + 告警 JSON,运行后生成,不入库)
├── server-scan.conf.example # 统一配置示例(所有扫描脚本共用一份)
└── notify.conf.example # 通知配置示例(含密钥,需 chmod 600)
分析脚本统一收拢在
core/,根目录只保留server-scan作为全局入口。 脚本通过SCRIPT_DIR自动定位项目根目录,因此lib/、配置文件、通知配置的查找路径均不受影响。
# 赋予执行权限
chmod +x server-scan core/*.sh
# 查看帮助
./server-scan --help
# 运行系统瓶颈总览
./server-scan overview
# 磁盘专项分析
./server-scan disk
# 指定目录扫描(只扫描指定目录,跳过全盘扫描)
./server-scan disk -d /var/log
./server-scan disk -d /var/log -d /home/user
./server-scan disk -d "/var/log /home/user" --depth 5 --top 30
# 分类扫描(只关注部分类别,章节号自动连续)
./server-scan disk --only docker
./server-scan disk --only docker,temp
./server-scan disk --only usage
# Docker 数据目录非默认时(如 data-root 迁到 /data/docker),指定目录扫描
./server-scan disk --only docker --docker-dir /data/docker
# 扫描杀毒软件 / 主机安全防护
./server-scan security
# 运行所有诊断
./server-scan all./core/sys_overview.sh
./core/cpu_mem_analyzer.sh
./core/disk_analyzer.sh
./core/network_analyzer.sh
./core/security_scanner.sh所有脚本支持以下公共选项:
| 选项 | 说明 |
|---|---|
-o, --output PATH |
报告输出路径(默认: output/<脚本>/<脚本>_<时间戳>.md,可用 OUTPUT_DIR 环境变量修改根目录) |
-c, --config FILE |
指定配置文件(覆盖默认配置文件查找) |
-q, --quiet |
静默模式(只输出报告路径一行,供 Agent 解析) |
--json |
在 stdout 输出一行 JSON 元数据(供 Agent 程序化消费) |
--no-color |
禁用 ANSI 颜色(Agent 调用时必需) |
--lang LANG |
指定输出语言(zh_CN / en_US,默认跟随系统 LANG) |
--notify |
启用通知推送(默认已启用,此参数用于显式声明) |
--no-notify |
关闭本次运行的通知推送 |
--notify-channel NAME |
指定通知渠道(默认: feishu) |
--webhook URL |
指定 webhook 地址(覆盖配置文件) |
--notify-test |
发送一条测试消息,验证通知配置是否正确 |
-h, --help |
显示帮助信息 |
core/disk_analyzer.sh:
| 选项 | 说明 |
|---|---|
-d, --dir DIR |
指定扫描目录(可多次指定或使用空格分隔多个目录) |
--depth N |
子目录扫描深度(默认: 3) |
--top N |
显示 Top N 结果(默认: 20) |
--only CAT[,CAT] |
只扫描指定类别(默认 all),详见下方分类扫描 |
--docker-dir DIR |
指定 Docker 数据目录(data-root 非默认时使用,优先级最高) |
--docker-log-dir DIR |
指定 Docker 容器日志目录(默认: <数据目录>/containers) |
core/network_analyzer.sh:
| 选项 | 说明 |
|---|---|
--ping-targets "IP1 IP2" |
连通性探测目标(默认: 8.8.8.8 1.1.1.1) |
--dns-targets "D1 D2" |
DNS 解析测试域名(默认: www.baidu.com www.google.com) |
core/cpu_mem_analyzer.sh:
| 选项 | 说明 |
|---|---|
--no-mpstat |
禁用多核采样(Linux 下有效) |
--interval N |
采样间隔(秒,默认: 1) |
--count N |
采样次数(默认: 3) |
默认扫描全部类别。使用 --only 只扫描关注的部分,章节号会自动保持连续:
| 类别 | 覆盖内容 |
|---|---|
usage |
磁盘基础信息、空间使用率、inode 使用率 |
io |
I/O 性能采样(含实时 I/O 快照,需 ENABLE_REALTIME_IO=true) |
large |
大文件与目录扫描 |
logs |
日志文件专项扫描 |
lvm |
LVM 逻辑卷信息 |
health |
磁盘健康状态 (SMART) |
mount |
挂载参数与文件系统特性 |
docker |
Docker 空间占用专项扫描 |
temp |
临时文件与缓存占用 |
all |
全部类别(默认) |
# 只看 Docker 空间占用
./server-scan disk --only docker
# 同时看 Docker 与临时文件
./server-scan disk --only docker,temp
# 只看空间与 inode(最快速的健康检查)
./server-scan disk --only usagedocker 类别依赖 Docker 数据目录,解析优先级为:
--docker-dir 命令行参数 > 配置文件 DOCKER_DATA_DIR > docker info 探测 > 默认 /var/lib/docker
当 docker 的 data-root 被改为非默认路径(常见于数据盘独立挂载,如 /data/docker)时,
必须显式指定,否则会误扫 /var/lib/docker —— 该目录在迁移后常作为残留空目录保留,
会使空间统计严重失真。指定的路径无效时会输出告警并回退自动探测,不会静默出错。
容器日志目录默认取 <数据目录>/containers;若日志与数据目录分离,可用 --docker-log-dir
或配置文件 DOCKER_LOG_DIR 单独指定。即便 docker 命令不可用,只要显式指定了数据目录,
仍会执行目录级空间与日志扫描。
temp 类别会扫描 /tmp、/var/tmp 以及系统缓存目录(Linux: /var/cache、~/.cache;macOS: ~/Library/Caches),
输出各目录占用、大文件 Top N、长期未访问的清理候选与可清理空间合计。
脚本只给出清理建议,不会删除任何文件。
--only与-d/--dir互斥:目录模式只扫描指定目录,分类过滤不适用。
产物默认保存在项目根目录的 output/ 下,按脚本标识分目录归档,便于查看历史与清理:
output/
├── sys_overview/
│ ├── sys_overview_20260904_094218.md # Markdown 报告(人类阅读)
│ └── sys_overview_20260904_094218.json # 结构化告警(机器消费)
├── disk/
│ └── disk_20260904_094545.{md,json}
├── cpu_mem/
├── network/
└── security/
- 同一文件名成对出现:
.md报告 +.json结构化告警,JSON 路径即把报告后缀.md换成.json - 产物根目录可用
OUTPUT_DIR环境变量覆盖(如OUTPUT_DIR=/var/log/server-scan),也可用-o完全自定义路径 - 告警 JSON 与 Markdown 报告同源于一次扫描,避免两份结果不一致
- 产物目录不纳入版本控制(见
.gitignore)
告警 JSON 结构(schema_version: 1.0):
{
"schema_version": "1.0",
"script": "sys_overview.sh",
"hostname": "server01",
"timestamp": "2026-09-04T01:42:21Z",
"report_path": "output/sys_overview/sys_overview_20260904_094218.md",
"summary": {"total": 2, "critical": 1, "warning": 0, "info": 0},
"alerts": [
{"level": "critical", "dimension": "磁盘", "metric": "磁盘使用率",
"object": "/dev/disk5s1", "value": "97%", "threshold": "90%",
"detail": "挂载点 /private/var/run/...", "suggestion": "清理该挂载点或扩容"}
]
}字段含义:level(critical/warning/info)、dimension 维度、metric 指标名、object 对象
(如文件系统)、value 当前值、threshold 阈值、detail 补充细节、suggestion 建议。
每个 alert 压缩为单行,notify 用 grep/sed 即可零依赖解析,整体仍是合法 JSON。
通知推送(默认启用,可用 --no-notify 关闭)直接读取该 JSON 的 alerts 字段构造推送正文——
字段语义明确,不依赖从 Markdown 文本反向解析告警行。五个分析脚本现已全部产出结构化告警 JSON。
# 静默模式:只输出报告路径一行
./server-scan overview --quiet
# 输出: output/sys_overview/sys_overview_20240101_120000.md
# JSON 输出:输出结构化元数据
./server-scan overview --json
# 输出:
# {
# "status": "success",
# "report_path": "output/sys_overview/sys_overview_20240101_120000.md",
# "timestamp": "2024-01-01T12:00:00Z",
# "hostname": "server01",
# "script": "sys_overview.sh",
# "duration_sec": 5,
# "summary": "",
# "bottlenecks": ""
# }| 退出码 | 含义 |
|---|---|
| 0 | 成功 |
| 1 | 发现瓶颈(或检测到防护软件) |
| 2 | 参数错误 |
支持中英文双语输出,语言优先级:SS_LANG 环境变量 > 系统 LANG > 默认中文。
# 默认中文(跟随系统语言)
./server-scan overview
# 临时切换为英文(环境变量)
SS_LANG=en_US ./server-scan overview
# 通过参数指定语言(仅当次运行生效)
./server-scan --lang en_US overview语言包位于 lib/i18n/(zh_CN.sh、en_US.sh),新增语言只需复制模板并翻译。
- Linux: CentOS / Ubuntu / Debian / RHEL
- macOS: Intel / Apple Silicon
Linux:
# CentOS/RHEL
yum install -y sysstat smartmontools bc
# Ubuntu/Debian
apt install -y sysstat smartmontools bcmacOS:
brew install coreutils smartmontools系统总览报告 (core/sys_overview.sh)
- CPU / 内存 / 磁盘 / 网络 快速扫描
- 综合健康度评分与瓶颈结论
- 各维度瓶颈清单
CPU / 内存报告 (core/cpu_mem_analyzer.sh)
- CPU 基础信息与负载评估
- CPU 时间分布与多核采样
- 内存总体概况与 Swap 分析
- OOM 风险评估
- 进程状态分布与资源消耗 Top 10
- 上下文切换与系统句柄统计
磁盘报告 (core/disk_analyzer.sh)
- 块设备列表与 I/O 调度器
- 磁盘空间与 inode 使用率
- I/O 性能采样与实时负载快照
- 大文件与日志扫描
- LVM 逻辑卷信息
- SMART 健康状态
- Docker 空间占用专项扫描
- 指定目录空间占用分析
网络报告 (core/network_analyzer.sh)
- 网络接口状态与流量
- 连通性测试(可自定义目标)
- TCP 连接状态统计
- 端口监听扫描
- DNS 解析测试
- 丢包与延迟分析
安全扫描报告 (core/security_scanner.sh)
- 内置 20+ 款常见防护软件特征库(ClamAV / CrowdStrike / 云盾 / 云镜 / Wazuh 等)
- 四类信号交叉检测:进程名、systemd 服务、安装包(rpm/dpkg)、特征路径
- 按类别分类:传统杀毒 / 主机安全 (HIDS) / EDR 终端防护
- 检测结论与部署建议(只读检测,不会停止或修改任何防护软件)
# 修改报告输出路径
./server-scan overview -o /var/log/report.md
# 指定目录扫描
./server-scan disk -d /var/log --depth 5 --top 30所有扫描脚本共用一份配置文件 server-scan.conf,按变量名前缀各取所需,
不需要为每个脚本各建一个配置文件:
cp server-scan.conf.example server-scan.conf# ---- 磁盘专项(disk_analyzer.sh)----
# 磁盘使用率警告阈值(%)
DISK_USAGE_WARNING_THRESHOLD=80
# 磁盘使用率危险阈值(%)
DISK_USAGE_CRITICAL_THRESHOLD=90
# I/O await 优秀阈值(ms)
IO_AWAIT_EXCELLENT_THRESHOLD=10
# 自定义 Docker 数据目录
DOCKER_DATA_DIR=""
# Docker 镜像 Top N
DOCKER_IMAGE_TOP=15
# ---- CPU 与内存专项(cpu_mem_analyzer.sh)----
# 采样间隔(秒)
SAMPLE_INTERVAL=1
# Swap 使用率告警阈值(%)
SWAP_USAGE_WARNING_THRESHOLD=50
# 僵尸进程 critical 阈值(个)
ZOMBIE_CRITICAL_THRESHOLD=50
# D 状态进程告警阈值(个)
D_STATE_WARNING_THRESHOLD=5书写约定:注释请独占一行,放在变量上方,不要写成
KEY=value # 注释。 这样可以从源头避免「值里含#时被误判为注释」的歧义。
- 值含空格或特殊字符(含
#)时请用引号:KEY="a #b",引号内的#会完整保留- 未加引号的值中,空白之后的
#仍按 shell 惯例视为注释(abc#def不受影响)- 已有行内注释无需手工改,
config upgrade会自动整理为独占一行
完整示例见 server-scan.conf.example。
配置文件查找顺序(找到即用,优先级从高到低):
- 命令行
-c/--config指定 - 环境变量
CONFIG_FILE $SCRIPT_DIR/server-scan.conf$SCRIPT_DIR/disk_analyzer.conf(旧版兼容,新文件不存在时才回退)
通知推送配置独立为
notify.conf:其中含 webhook 与签名密钥, 需单独设置chmod 600,不与普通配置项混用。详见下方 通知推送 (Channel),示例文件为notify.conf.example。
配置会随版本演进(文件更名、新增或废弃配置项),用 server-scan config 自动处理,
无需手工复制粘贴:
./server-scan config check # 检查: 生效文件、拼写错误/已废弃项、缺失的新增项
./server-scan config upgrade # 用示例配置补齐新增项(保留已有值,自动备份)
./server-scan config migrate # 旧版 disk_analyzer.conf 迁移到统一配置
./server-scan config show # 显示当前生效的配置文件与内容| 操作 | 行为 | 备份 |
|---|---|---|
check |
报告生效文件与来源、不在示例中的可疑键、尚未写入的新增键;有问题时退出码 1 | 不修改 |
upgrade |
只追加当前配置缺失的键(取自示例的默认值),已有值与注释原样保留 | server-scan.conf.bak |
migrate |
统一配置不存在时以旧文件为基础生成;已存在时只补入旧文件独有键,不覆盖现有值 | 旧文件改名 disk_analyzer.conf.bak |
若仍在使用旧版 disk_analyzer.conf,每次扫描会提示执行 config migrate。
支持将扫描结果推送到外部 Channel,当前内置飞书自定义机器人。
# 1. 复制配置文件模板
cp notify.conf.example notify.conf
# 2. 填入 webhook(飞书: 群设置 -> 群机器人 -> 添加自定义机器人)
vi notify.conf
# 3. 设置权限(配置文件含密钥,禁止其他用户读取)
chmod 600 notify.conf
# 4. 验证配置是否正确
./server-scan overview --notify-test
# 5. 执行扫描(默认即推送,无需额外参数)
./server-scan overview| 配置项 | 默认值 | 说明 |
|---|---|---|
NOTIFY_ENABLED |
true |
是否启用推送(默认启用);设为 false 可全局关闭 |
NOTIFY_CHANNEL |
feishu |
通知渠道,当前支持 feishu |
NOTIFY_WEBHOOK |
空 | Webhook 地址(必填) |
NOTIFY_SECRET |
空 | 签名密钥,机器人开启签名校验时填写 |
NOTIFY_MSG_TYPE |
text |
消息类型:text 纯文本 / card 交互式卡片 |
NOTIFY_MODE |
summary |
summary 仅推送告警摘要 / full 推送完整报告 |
NOTIFY_MAX_BYTES |
20000 |
全文模式下正文最大字节数 |
NOTIFY_TIMEOUT |
10 |
HTTP 请求超时(秒) |
NOTIFY_ON_ALERT_ONLY |
false |
仅在检测到告警(🔴/🟡)时推送 |
NOTIFY_MENTION_ALL |
false |
是否 @所有人 |
NOTIFY_MENTION_IDS |
空 | @指定用户 open_id,逗号分隔 |
NOTIFY_SUMMARY_LINES |
20 |
摘要模式提取的告警行上限 |
NOTIFY_TABLE_STYLE |
kv |
表格呈现:kv 转列表 / code 代码块 / raw 原样 |
默认启用,失败不阻塞:扫描结束后即推送通知,无需加
--notify。 若未配置NOTIFY_WEBHOOK、网络异常或渠道不支持,只会输出一条⚠️告警并跳过推送, 扫描结果与退出码不受影响(告警写 stderr,且在--json/--quiet下静默)。 不需要推送时用--no-notify(单次)或NOTIFY_ENABLED=false(全局)关闭。
命令行参数 > 环境变量 > 配置文件。
配置文件查找顺序(找到第一个存在的文件即停止):
$NOTIFY_CONFIG- 脚本
-c/--config指定的配置文件 $SCRIPT_DIR/notify.conf$HOME/.server-scan/notify.conf/etc/server-scan/notify.conf
# 默认即推送(无需额外参数)
./server-scan overview
# 单次关闭推送
./server-scan overview --no-notify
# 临时指定 webhook(调试用;webhook 会出现在进程列表中)
./server-scan disk --notify --webhook "https://open.feishu.cn/open-apis/bot/v2/hook/xxx"
# 定时巡检,仅在有告警时推送(避免正常状态刷屏)
NOTIFY_ON_ALERT_ONLY=true ./server-scan overview --notify
# 使用非默认路径的配置文件
NOTIFY_CONFIG=/etc/server-scan/notify.conf ./server-scan network --notify
# 推送完整报告并使用卡片消息
NOTIFY_MODE=full NOTIFY_MSG_TYPE=card ./server-scan overview --notify飞书 text 与卡片 lark_md 都不支持 Markdown 表格,直接推送原报告会出现大量裸竖线,
可读性很差。脚本默认(NOTIFY_TABLE_STYLE=kv)把表格转换为结构化列表:
转换前(报告中的表格):
| 级别 | 维度 | 结论 |
|------|------|------|
| 🔴 | 磁盘 | /var 使用率 97%(>= 90%) |
转换后(飞书消息中):
🔴 **磁盘**: /var 使用率 97%(>= 90%)
卡片模式下 **加粗** 会被渲染,状态 emoji 也会正常显示。
如需保留原始表格,可设置 NOTIFY_TABLE_STYLE=code(表格以代码块等宽展示)或 raw(不做转换)。
notify.conf可能包含 webhook 与签名密钥,已加入.gitignore,请勿提交到代码仓库- 建议设置
chmod 600 notify.conf;权限过宽时脚本会给出警告 --webhook参数会出现在进程列表中,生产环境建议改用配置文件- 推送失败不会影响扫描本身,也不会改变脚本退出码
# 打开交互菜单:查看 / 添加 / 删除
./server-scan cron
# 也可直接使用子命令
./server-scan cron list # 查看已有的定时任务
./server-scan cron add # 添加
./server-scan cron remove # 删除添加流程会依次引导你选择:扫描任务 → 执行频率(每小时/每天/每周/每月/自定义)→ 时间 →
报告输出目录 → 是否推送飞书(可选仅告警时推送)→ 附加参数(如 --only docker),
最后预览生成的 crontab 条目并确认后才会写入。
生成的条目示例:
# server-scan:overview
# 报告默认写入产物目录 output/,如需自定义落点可在命令中加 -o <目录>
30 2 * * * PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin /path/to/server-scan overview
安全设计:
- 只操作带
# server-scan:标记的条目,不会影响你已有的其他定时任务 - 每次写入前自动备份原 crontab 到
~/.server-scan/crontab.backup.<时间戳> - 条目内自动补全
PATH,避免 cron 环境下找不到iostat、smartctl等命令 - 自动把报告文件名中的
%转义为\%(cron 特殊字符)
也可以直接编辑 crontab:
# 每小时生成一次报告
0 * * * * /path/to/server-scan overview -o /var/log/sys_overview.md
0 * * * * /path/to/server-scan disk -o /var/log/disk_report.md
# 每天凌晨 2 点巡检,仅在发现告警时推送飞书
0 2 * * * NOTIFY_ON_ALERT_ONLY=true /path/to/server-scan overview手动配置时注意:cron 的
PATH与终端不同,建议使用绝对路径; 命令中的%需转义为\%,否则其后的内容会被当作标准输入。
MIT