人人都会AI编程

服务状态监控与告警脚本

更新时间:2026-07-12

在生产环境中,服务偶尔会出现不可预料的宕机、僵死或响应异常。完全依赖人工巡检既不现实也不可靠,因此编写轻量级监控脚本,并配合系统定时任务自动执行和告警,是运维工作中最基础也最有效的防线。

设计思路

一个实用的监控脚本通常遵循几个原则:

  • 只做一件事:每次检查一个服务的关键指标,如进程存活、端口监听、HTTP 状态码等;
  • 静默但可查:脚本正常时不输出无关内容,仅在故障时将详情写入标准输出或日志;
  • 告警方式灵活:通过邮件、钉钉/企业微信机器人或短信接口推送故障信息,必要时可反复重试;
  • 幂等性:多次执行不会重复告警(可通过临时文件记录上一次状态实现)。

常用命令工具

监控脚本离不开这些基础工具:

  • pspgrep:检查进程是否存在
  • ssnetstat:查看端口监听状态
  • curlwget:检测 HTTP/HTTPS 服务响应
  • systemctl is-active(Systemd 系统):直接询问服务的运行状态
  • mailsendmail:发送告警邮件
  • curl 配合 Webhook 地址:推送消息到钉钉、企业微信、Slack 等

实例:监控 Nginx 进程与端口

下面是一个完整的 Bash 脚本,用于监控 Nginx 服务是否存活。它检查进程名和 TCP 80 端口,若有一项失败则发送告警邮件,并记录日志。

#!/bin/bash
# 监控 Nginx 状态脚本

SERVICE="nginx"
PORT=80
ALERT_EMAIL="admin@example.com"
LOG_FILE="/var/log/check_nginx.log"

# 检查进程
pgrep -x "$SERVICE" > /dev/null
PROC_OK=$?

# 检查端口是否在监听
ss -tlnp | grep -q ":$PORT "
PORT_OK=$?

if [ $PROC_OK -ne 0 ] || [ $PORT_OK -ne 0 ]; then
    DATE=$(date '+%Y-%m-%d %H:%M:%S')
    echo "[$DATE] ALERT: $SERVICE is down! Process=$PROC_OK Port=$PORT_OK" >> "$LOG_FILE"
    
    # 构造邮件内容
    SUBJECT="[$SERVICE] Service Down Alert"
    BODY="$SERVICE is not running on $(hostname) at $DATE.
Process check: $([ $PROC_OK -eq 0 ] && echo OK || echo FAILED)
Port $PORT check: $([ $PORT_OK -eq 0 ] && echo OK || echo FAILED)"
    
    echo "$BODY" | mail -s "$SUBJECT" "$ALERT_EMAIL"
fi

脚本解释:

  • pgrep -x 严格匹配进程名,避免误判类似名称的进程;
  • ss -tlnp 列出所有监听的 TCP 端口,再通过 grep 过滤指定端口;
  • 任一检查失败,就记录日志并发送邮件。正常时脚本不产生任何输出,适合放入 crontab

实例:监控一个 Web 接口的可用性

很多后端服务虽然没有独立端口,但会暴露一个健康检查接口(如 /health)。使用 curl 可以判断服务是否真正在正常工作:

#!/bin/bash
URL="http://127.0.0.1:8080/health"
EXPECTED_CODE=200
ALERT_WEBHOOK="https://hooks.slack.com/services/xxx/yyy/zzz"

HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" --max-time 5 "$URL")
if [ "$HTTP_CODE" != "$EXPECTED_CODE" ]; then
    DATE=$(date '+%Y-%m-%d %H:%M:%S')
    MESSAGE="[$DATE] CRITICAL: $URL returned $HTTP_CODE, expected $EXPECTED_CODE"
    echo "$MESSAGE" >> /var/log/web_health.log
    
    # 通过 Slack Webhook 发送告警
    curl -X POST -H 'Content-type: application/json' \
        --data "{\"text\":\"$MESSAGE\"}" "$ALERT_WEBHOOK"
fi

关键点:

  • curl--max-time 防止脚本因网络超时而阻塞;
  • -w "%{http_code}" 只获取状态码,-o /dev/null 丢弃页面内容,干净高效;
  • 告警方式换成了 Slack Webhook,也可以同样适配企业微信或钉钉机器人,只需修改 URL 和 JSON 格式。

定时运行:cron 配置

监控脚本写好之后,通过 cron 系统服务按固定频率执行。例如每分钟检查一次 Nginx:

* * * * * /usr/local/bin/check_nginx.sh >/dev/null 2>&1

建议将脚本的错误输出也重定向,避免 cron 默认发送多余的系统邮件。如果脚本自身已经处理了告警,cron 这一行就可以完全静默。

进阶技巧:防止告警风暴

如果服务长时间未恢复,每分钟一封邮件会迅速淹没收件箱。简单方案是增加状态文件,只在状态发生变化时告警:

STATE_FILE="/tmp/nginx_alert.state"
# 从状态文件中读取上次状态(0=正常, 1=异常)
LAST_STATE=$(cat "$STATE_FILE" 2>/dev/null || echo 0)
# 当前异常则 CURRENT_STATE=1,否则为0
...
if [ $CURRENT_STATE -ne $LAST_STATE ]; then
    # 发送告警
    echo "$CURRENT_STATE" > "$STATE_FILE"
fi

总结

服务监控脚本并不需要复杂框架,几个基础命令搭配 Shell 逻辑,就能覆盖 80% 以上的常见监控需求。它们的价值在于:

  • 轻量:不依赖第三方监控系统即可运行;
  • 透明:逻辑一目了然,容易修改和调试;
  • 可组合:可作为更大监控系统(如 Nagios、Zabbix)的检测插件,也可以单独使用。

对于任何运维或开发者而言,编写和维护一份这样的脚本,是确保线上服务可靠性的第一道关卡。