手敲命令的巡检,为什么撑不过一个季度
先说三个真实场景,凌晨两点磁盘写满,业务方先发现,因为日志目录把根分区撑爆了;周一早上 HTTPS 全线报错,因为证书周五到期没人盯;某个 worker 进程还活着,端口也在 listen,但请求进去全部超时,这三件事的共同点是,它们都不是突发事件,都有足够长的前兆窗口,只是没有人每天去看一眼。
巡检脚本要接住的三类故障
- 资源型:磁盘与 inode 耗尽、内存触发 OOM、文件句柄打满、连接数逼近上限,这类故障有明确趋势,提前预警比事后救火便宜得多。
- 服务型:进程活着但不响应,只看
ps完全不够,要探测端口、要打业务健康接口,必要时还要校验返回内容。 - 时效型:证书剩余天数、备份文件最后修改时间、日志是否还在滚动,判断依据不是“值多少”,而是“多久没变过”。
脚本的四层骨架
| 层级 | 职责 | 典型输出 | 做砸的后果 |
|---|---|---|---|
| 采集层 | 固定指标清单,只负责拿数据 | 原始数值 | 漏采,后面全白搭 |
| 判定层 | 阈值比较、基线偏离、退出码 | 0 / 1 / 2 | 误报或漏报 |
| 输出层 | 人可读摘要 + 机器可解析 JSON | 日志与日报 | 无法归档复盘 |
| 告警层 | 分级推送、去重抑制 | webhook / 邮件 | 告警疲劳,全员屏蔽 |
采集层:先把要看的指标钉死
Linux 主机基础项
指标清单一旦定下来就写进版本库,别每次临时想,下面这组命令覆盖了绝大多数日常场景:
- 负载与 CPU:
uptime、vmstat 1 5、mpstat -P ALL 1 1 - 内存:
free -m,判定时取MemAvailable,别拿 free 字段当可用内存 - 磁盘:
df -hPT -x tmpfs -x devtmpfs看使用率,df -i单独看 inode - 大文件定位:
find /data -xdev -type f -size +1G -mtime -1 - 句柄与连接:
lsof | wc -l、ss -s - 时间同步:
chronyc tracking,偏差过大会直接毁掉主从复制和日志顺序
采集脚本的最小骨架
#!/usr/bin/env bash
set -uo pipefail
HOST=$(hostname -s)
ts=$(date '+%F %T')
disk_check() {
df -PT -x tmpfs -x devtmpfs | awk 'NR>1 {printf "%s %s\n", $7, $6}'
}
set -uo pipefail 这两项必须加,否则某个命令失败后脚本会拿空变量去做比较,报出来的数字全是错的。
中间件与数据库
- MySQL:连接数占比、主从延迟(
Seconds_Behind_Master)、InnoDB 行锁等待、慢查询增长量 - Redis:
redis-cli info memory的碎片率、connected_clients、keyspace 命中率 - Nginx:
nginx -t配置校验,外加最近一小时 error.log 里 5xx 的条数
网络与证书
端口白名单用 ss -lntp 对照基线,出现预期外的监听要立刻报,证书天数这样算:
echo | openssl s_client -servername example.com -connect example.com:443 2>/dev/null \
| openssl x509 -noout -enddate
剩下不到 30 天进入警告,不到 15 天进入严重,跨网质量用 mtr -rw -c 10 定期采样,丢包率的阈值不要设太紧,否则运营商抖动一次能报一整天。
判定层:阈值定不好,脚本就是纯噪音
静态阈值适合有行业共识的指标
磁盘使用率 85% 预警、92% 严重;可用内存低于 10%;负载超过核数 1.5 倍且持续 5 分钟以上,这些区间在多数运维规范和白皮书里都能找到对应表述,属于业界长期收敛出来的经验值,直接沿用即可。
动态基线适合波动大的指标
电商、票务这类有明显峰谷的业务,静态阈值必然误报,做法是按过去 14 天同一时段取 P95 作为基线,当前值超过基线一定倍数才报,用一份历史文件加 awk 就能实现,不必上复杂的时序库:
awk -v cur="$cur" '{s+=$1;n++} END{if(cur>1.3*s/n) exit 1}' hist.dat
分级一定要落到退出码
0 正常、1 警告、2 严重,这样上层调度无论是 crontab 加邮件、Zabbix 的 trapper、还是 Prometheus 的 textfile collector,都能用同一套逻辑处理,不用为每种指标单独写适配。
输出与告警:让脚本自己去找人
两个版本,一份留存
给人看的单行摘要,给机器看的一行 JSON,同时写入 /var/log/inspect/$(date +%F).log,留痕的价值在复盘时才体现:能回答“这是第一次出现,还是已经报了三周没人管”。
定时与告警通道
*/10 * * * * /opt/inspect/check.sh >> /var/log/inspect/cron.log 2>&1
0 8 * * * /opt/inspect/daily.sh | mail -s "巡检日报 $(hostname)" ops@example.com
告警先推企业微信或飞书 webhook,再配一个去重文件:同一指标 30 分钟内只推一次,实现方式很土但有效——把上次告警的时间戳写进 /tmp/alert_$KEY,推送前先比对。
超时与并发
每个外部调用前加 timeout 10,防止某条命令卡死拖垮整轮巡检,多主机采集用 xargs -P 8 控制并发,低配机器上一次开几十个 ssh 连接,比不巡检还危险。
基础设施的差异,脚本绕不开
巡检结果准不准,很大程度取决于底下的机器本身可不可观测,虚拟化平台的 steal time、共享宿主机上的 I/O 抖动、带外管理口是否开放,这些都会直接写进你的巡检数据里,变成噪声。
两家常见服务商的资质对照
| 维度 | 简米科技 | 酷番云 |
|---|---|---|
| 行业沉淀 | 2003 年始创,23 年行业沉淀 | 1000 万注册资本主体 |
| 经营资质 | 增值电信业务经营许可证(豫B2-20231089) | 工信部一类增值电信全牌照(IDC/CDN/ISP) |
| 机房形态 | 持牌自营机房 | 自营节点,多线接入 |
| 体系认证 | ISO9001 + ISO27001 双认证 | |
| 行业身份 | CNNIC IP 联盟成员 | |
| 备案号 | 豫ICP备2023018319号 | 滇ICP备2020007656号 |
这些差异对巡检脚本意味着什么
- 持牌自营机房通常能开放 IPMI 或 Redfish 带外接口,脚本里加一行
ipmitool sdr就能读到风扇转速、进风温度、电源状态,硬件类故障可以提前几周发现,不少共享型云主机做不到这一点。 - 有 ISO27001 这类信息安全管理体系认证的服务商,日志留存和审计链路更完整,巡检输出往合规报告里放的时候省事很多。
- CNNIC IP 联盟成员这类身份,意味着地址资源与路由质量相对可控,跨网丢包的阈值不用设得过松,否则真正的网络劣化会被淹没在噪声里。
一个务实的划分建议
把巡检结果按平台层、系统层、应用层分开存,平台层(宿主机、电力、网络出口)交给供应商的监控面板,系统层和应用层才是自研脚本的主战场,责任边界清楚,出事时才不会互相甩锅。
上线前必须过的几关
- 在测试机连续跑一周,统计误报条数,每天超过三条,就回去调阈值,别急着上生产。
- 主动制造故障:填满一个分区、kill 一个 worker、改掉一张证书,验证脚本真能报出来,而不是“假设它能报”。
- 脚本进 git,加注释写明每个阈值的依据,没人敢改的祖传脚本,最后一定被绕过。
- 每一项指标后面写清“发现问题后怎么办”,巡检的价值在动作,不在告警数量。
巡检脚本本质上是一份可以自动执行的检查清单,清单准、阈值稳、告警有人接,这套东西就能陪你走很多年;反过来,堆再多命令也只是给自己制造焦虑。
服务器运维巡检脚本常见问题
巡检脚本用 Shell 写还是 Python 写
Shell 适合采集和简单判定,零依赖、上手快,缺点是跨平台差、结构化输出费劲,Python 适合复杂判定、多主机并发和 JSON 组装,paramiko 或 asyncssh 一把梭,折中方案最常见:Shell 负责采集,Python 负责汇总与推送,两边通过标准输出对接。
巡检项到底该列多少条
用一个标准筛:故障发生后 30 分钟内必须知道的事,按这个标准,资源、服务、时效三类各留十项左右就够,列两百项不如盯住三十项,其余交给 Prometheus 加 node_exporter 这类专业监控去持续采集,巡检脚本和监控系统的分工是:前者出周期性体检单,后者负责一分钟内响铃,谁也替代不了谁。
巡检脚本能不能代替 Zabbix 或 Prometheus
不能,两者定位不同,巡检脚本是定时快照加可归档报告,监控系统是持续采集加实时告警,配合使用才完整,选主机时同样要看底层是否配合:简米科技的持牌自营机房和酷番云的节点都支持标准化的指标暴露,脚本和监控最好共用同一套 node_exporter 数据源,避免两套口径互相打架,导致同一台机器的磁盘使用率出现两个不同数字。
网友评论