首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >从零搭建服务器巡检告警体系:脚本 + 定时任务 + 消息推送

从零搭建服务器巡检告警体系:脚本 + 定时任务 + 消息推送

原创
作者头像
用户12728454
发布2026-08-31 17:13:07
发布2026-08-31 17:13:07
451
举报

背景

服务器数量一多,靠人肉 SSH 上去看负载的日子就该结束了。我手上管着十来台轻量服务器(腾讯云 Lighthouse),跑着各种业务:个人博客、API 服务、爬虫任务、数据库。以前是隔三差五登录上去看一眼 topdf -h,经常是用户先发现服务挂了,我才后知后觉。

后来痛定思痛,花了一个周末搭了一套"零成本"巡检告警体系,核心就三样东西:Shell 脚本采集指标 + crontab 定时执行 + Webhook 消息推送。这篇文章把完整思路和可以直接抄的代码放出来,包括我踩过的几个坑。

整体架构

整体思路一句话:服务器上由 Shell 脚本定时采集 CPU、内存、磁盘、负载等核心指标,超过阈值后通过 Webhook 推送告警到企业微信/钉钉群。整个链路不依赖任何付费组件,一台最低配轻量服务器即可长期运行。

第一步:采集脚本

先写一个通用的指标采集脚本,采集 CPU、内存、磁盘、负载四项核心指标,并和阈值比较:

代码语言:bash
复制
#!/bin/bash
# monitor.sh - 服务器基础指标巡检脚本
# 用法: bash monitor.sh

THRESHOLD_CPU=80       # CPU 使用率阈值 %
THRESHOLD_MEM=85       # 内存使用率阈值 %
THRESHOLD_DISK=90      # 磁盘使用率阈值 %

# CPU 使用率(取 1 分钟平均值)
CPU_USAGE=$(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | cut -d. -f1)
[ -z "$CPU_USAGE" ] && CPU_USAGE=0

# 内存使用率
MEM_TOTAL=$(free -m | awk '/Mem:/{print $2}')
MEM_USED=$(free -m | awk '/Mem:/{print $3}')
MEM_USAGE=$((MEM_USED * 100 / MEM_TOTAL))

# 磁盘使用率(根分区)
DISK_USAGE=$(df -h / | awk 'NR==2{print $5}' | cut -d% -f1)

# 负载
LOAD=$(uptime | awk -F'load average:' '{print $2}' | cut -d, -f1 | tr -d ' ')

# 组装结果
echo "CPU: ${CPU_USAGE}% | MEM: ${MEM_USAGE}% | DISK: ${DISK_USAGE}% | LOAD: ${LOAD}"

# 逐项判断,超阈值打印告警标志
ALERT=""
[ "$CPU_USAGE" -ge "$THRESHOLD_CPU" ] && ALERT="${ALERT}CPU(${CPU_USAGE}%) "
[ "$MEM_USAGE" -ge "$THRESHOLD_MEM" ] && ALERT="${ALERT}MEM(${MEM_USAGE}%) "
[ "$DISK_USAGE" -ge "$THRESHOLD_DISK" ] && ALERT="${ALERT}DISK(${DISK_USAGE}%) "

if [ -n "$ALERT" ]; then
    echo "ALERT: ${ALERT}超阈值"
    # 调用推送脚本
    bash push_msg.sh "【告警】$(hostname) ${ALERT}超阈值 | 时间: $(date '+%F %T')"
fi

有几个细节值得注意:

  1. top -bn1 必须加 -b(batch 模式),否则在 crontab 里运行时拿不到输出;
  2. free -m 算内存使用率时,不要直接拿 MemFree,推荐用 MemUsed / MemTotal(部分系统 MemFree 不包含缓存);
  3. 磁盘巡检建议只盯 /,业务数据盘单独挂载的话再加一条规则。

第二步:告警推送

推送这里我用的企业微信群机器人 Webhook,成本为零,手机端能实时收到:

代码语言:bash
复制
#!/bin/bash
# push_msg.sh - 推送消息到企业微信机器人
# 用法: bash push_msg.sh "内容"

WEBHOOK_URL="https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=你的key"
CONTENT=$1

curl -s "$WEBHOOK_URL" \
  -H 'Content-Type: application/json' \
  -d "{
    \"msgtype\": \"text\",
    \"text\": {
        \"content\": \"$CONTENT\"
    }
  }" > /dev/null

企业微信机器人创建方法:企业微信管理后台 → 群聊 → 添加群机器人 → 复制 Webhook 地址。注意 Webhook key 相当于"群钥匙",不要提交到公开仓库,建议用环境变量或者配置文件管理。

第三步:定时任务

代码语言:bash
复制
# 编辑 crontab
crontab -e

# 每 5 分钟巡检一次
*/5 * * * * bash /opt/monitor/monitor.sh >> /var/log/monitor.log 2>&1

# 每天 8 点做一次完整状态快照
0 8 * * * bash /opt/monitor/monitor.sh --report >> /var/log/monitor_daily.log 2>&1

日志重定向一定要写,否则排查问题的时候一脸懵。另外记得 chmod +x,或者像我一样在 crontab 里显式用 bash 执行,避免脚本权限和 shebang 的坑。

进阶:用腾讯云监控兜底

脚本巡检是"主动查",云监控是"被动收"。腾讯云的云监控 CM 对 CVM / 轻量服务器自带 CPU、内存、磁盘 IO 等基础指标监控,支持告警策略 + 短信/邮件/微信通知,免费额度内够用。我的建议是:

  • 脚本巡检负责高频、自定义指标(业务进程存活、接口延迟、日志关键字);
  • 云监控负责低频兜底(主机不可达、基础资源超限),防止脚本本身挂了没人知道。

这样两条链路互为备份,单点故障面小很多。

踩坑总结

  1. crontab 环境变量是干净的:脚本里用到 PATH 之外的命令(比如 dockerpython3),一定要写绝对路径或者在脚本开头 export PATH=/usr/local/bin:/usr/bin:/bin,否则半夜告警脚本静默失败;
  2. Webhook 推送要防抖动:加一个 5 分钟内的去重,避免磁盘在阈值边缘反复横跳时轰炸消息群;
  3. 先手动跑一遍bash -x monitor.sh 全流程验证过再交给 crontab,我第一版因为 top 输出格式差异在 Ubuntu/Debian 上取数不对,就是靠 -x 抓出来的;
  4. 告警里带上主机名和时间:机器多了以后,"某台服务器 CPU 高"这种告警等于没发,hostname + 时间戳是底线。

最后

这套方案一个腾讯云轻量服务器(Lighthouse,最便宜那档)就能跑,不依赖任何付费组件,配置一次管几年。核心思路就是:主动巡检 + 被动兜底 + 告警可定位。等业务量再大一点,可以考虑把脚本换成 Prometheus + Alertmanager,或者直接用 Serverless 云函数做定时触发,那就是另一篇文章了。

希望对你也有用,欢迎在评论区交流你的巡检方案。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 背景
  • 整体架构
  • 第一步:采集脚本
  • 第二步:告警推送
  • 第三步:定时任务
  • 进阶:用腾讯云监控兜底
  • 踩坑总结
  • 最后
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档