在生产环境中,服务偶尔会出现不可预料的宕机、僵死或响应异常。完全依赖人工巡检既不现实也不可靠,因此编写轻量级监控脚本,并配合系统定时任务自动执行和告警,是运维工作中最基础也最有效的防线。
设计思路
一个实用的监控脚本通常遵循几个原则:
- 只做一件事:每次检查一个服务的关键指标,如进程存活、端口监听、HTTP 状态码等;
- 静默但可查:脚本正常时不输出无关内容,仅在故障时将详情写入标准输出或日志;
- 告警方式灵活:通过邮件、钉钉/企业微信机器人或短信接口推送故障信息,必要时可反复重试;
- 幂等性:多次执行不会重复告警(可通过临时文件记录上一次状态实现)。
常用命令工具
监控脚本离不开这些基础工具:
ps、pgrep:检查进程是否存在ss、netstat:查看端口监听状态curl、wget:检测 HTTP/HTTPS 服务响应systemctl is-active(Systemd 系统):直接询问服务的运行状态mail、sendmail:发送告警邮件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)的检测插件,也可以单独使用。
对于任何运维或开发者而言,编写和维护一份这样的脚本,是确保线上服务可靠性的第一道关卡。