前言
运维人员最怕什么?网站挂了自己还不知道。客户投诉了才发现,搜索引擎收录掉了才注意到——这种被动运维的痛,干过的都懂。
用 curl 批量检测网站状态码,再加上自动告警机制,就能把"事后救火"变成"事前预防"。本文分享5个从基础到进阶的实战方案,直接拿去用。
方案一:基础版——单次批量检测状态码
最核心的一条命令就搞定状态码采集:
curl -o /dev/null -s -w "%{http_code}" -m 5 https://example.com
参数解释:
-o /dev/null:丢弃响应体,只关心状态码-s:静默模式,不显示进度条-w "%{http_code}":只输出HTTP状态码-m 5:5秒超时,防止卡死
扩展成批量检测脚本:
#!/bin/bash
# url_list.txt 每行一个URL
while read -r url; do
code=$(curl -o /dev/null -s -w "%{http_code}" -m 5 "$url")
echo "$url -> $code"
done < url_list.txt
这种方式简单直接,适合手动巡检或者配合 cron 定期执行。缺点是没有告警,出了问题还得人去看日志。
方案二:带重试机制——避免误报
网络抖动导致一次检测失败就告警?太草率了。加个重试机制靠谱得多:
#!/bin/bash
URL_LIST="https://api1.example.com https://api2.example.com https://api3.example.com"
MAX_RETRY=3
TIMEOUT=5
check_url() {
local url=$1
local fail=0
for ((i=1; i<=MAX_RETRY; i++)); do
code=$(curl -o /dev/null -s -w "%{http_code}" -m $TIMEOUT "$url")
if [ "$code" -eq 200 ]; then
echo "$url [OK] 状态码: $code (第${i}次)"
return 0
fi
fail=$((fail+1))
echo "$url [RETRY $i/$MAX_RETRY] 状态码: $code"
sleep 2
done
echo "$url [FAIL] 连续${MAX_RETRY}次异常,状态码: $code"
# 触发告警
alert "$url" "$code"
return 1
}
for url in $URL_LIST; do
check_url "$url"
done
核心逻辑:连续3次检测都异常才触发告警。中间只要有一次返回200,就判定正常。这个阈值可以根据业务需求调整,对可用性要求高的服务可以把重试次数降到2次。
方案三:多指标检测——不只看状态码
光看状态码不够,还得看响应速度。一个200但响应要10秒的接口,用户体验也炸了。curl -w 可以同时采集多个指标:
#!/bin/bash
SLOW_THRESHOLD=3 # 慢请求阈值(秒)
URL_FILE="url_list.txt"
TIMEOUT=10
while read -r url; do
# 一次性采集状态码和各项时间
result=$(curl -o /dev/null -s -w "%{http_code}|%{time_connect}|%{time_starttransfer}|%{time_total}" -m $TIMEOUT "$url")
code=$(echo "$result" | cut -d'|' -f1)
connect=$(echo "$result" | cut -d'|' -f2)
ttfb=$(echo "$result" | cut -d'|' -f3)
total=$(echo "$result" | cut -d'|' -f4)
echo "$url | 状态码: $code | 连接: ${connect}s | TTFB: ${ttfb}s | 总耗时: ${total}s"
# 状态码异常告警
if [ "$code" -ne 200 ] && [ "$code" -ne 301 ] && [ "$code" -ne 302 ]; then
echo "[告警] $url 状态码异常: $code"
alert "$url" "状态码异常: $code"
fi
# 响应超时告警
if (( $(echo "$total > $SLOW_THRESHOLD" | bc -l) )); then
echo "[告警] $url 响应过慢: ${total}s"
alert "$url" "响应超时: ${total}s"
fi
done < "$URL_FILE"
采集指标说明:
time_connect:TCP连接耗时time_starttransfer:首字节时间(TTFB)time_total:总响应时间
这种方式能同时发现宕机和性能退化两类问题,告警准确率更高。
方案四:Webhook告警通知
检测到异常怎么通知人?邮件太慢,Webhook秒级到达。以钉钉机器人为例:
alert() {
local url=$1
local msg=$2
local webhook="https://oapi.dingtalk.com/robot/send?access_token=YOUR_TOKEN"
local timestamp=$(date +%s%3N)
# 生成签名(加签模式)
sign=$(echo -n "${timestamp}\nSEC_KEY" | openssl dgst -sha256 -hmac "SEC_KEY" -binary | base64)
encoded_sign=$(python3 -c "import urllib.parse; print(urllib.parse.quote('$sign'))")
local body="{\"msgtype\":\"text\",\"text\":{\"content\":\"[网站监控告警]\\nURL: $url\\n问题: $msg\\n时间: $(date '+%Y-%m-%d %H:%M:%S')\"}}"
curl -s -X POST "$webhook×tamp=$timestamp&sign=$encoded_sign" \
-H 'Content-Type: application/json' \
-d "$body" > /dev/null
}
支持的通知渠道可以根据团队习惯选择:
- 钉钉机器人 Webhook(国内团队首选)
- 企业微信 Webhook(配合加签验证)
- 飞书 Webhook(支持富文本卡片)
- Slack Webhook(海外团队常用)
- Telegram Bot(个人运维最方便)
把 alert 函数集成到前面的检测脚本中,检测到异常就自动推送。整个流程完全自动化,不需要人盯着。
方案五:cron定时巡检+日志轮转
脚本写好了,配上 cron 就是完整的自动化巡检系统:
# 每5分钟巡检一次
*/5 * * * * /opt/scripts/site_monitor.sh >> /var/log/site_monitor.log 2>&1
# 日志轮转配置 /etc/logrotate.d/site_monitor
/var/log/site_monitor.log {
daily
rotate 30
compress
missingok
notifempty
create 0644 root root
}
日志轮转别漏了,不然磁盘被日志撑爆就是新故障。建议保留30天的历史日志,出了问题可以回溯排查。
crontab 配置注意事项:
- 脚本路径用绝对路径,cron 环境变量和交互式 shell 不同
- curl 命令也建议用绝对路径:
/usr/bin/curl - 脚本开头加上
PATH=/usr/local/bin:/usr/bin:/bin - 检测频次建议5分钟,太频繁浪费资源,太间隔发现问题太晚
状态码判断技巧
不是所有非200都需要告警。合理的状态码分类:
- 正常范围:200、301、302(301/302是合法重定向)
- 需要告警:500、502、503(服务端故障)、0(连接超时或DNS解析失败)
- 看情况:404(如果是API接口就要告警,如果是静态资源可以忽略)、403(权限问题可能正常)
- 忽略:304(Not Modified,正常的缓存命中)
根据业务类型调整判断逻辑,避免无效告警导致告警疲劳。
总结
5个方案从简单到完善,覆盖了批量检测、重试容错、多维指标、自动告警、定时巡检的完整链路。建议根据实际场景组合使用:小站用方案二+方案四就够了,大团队用方案三+方案四+方案五搭建完整的监控体系。
脚本不复杂,但能解决实际问题。关键是"写完配上cron就别管了"——真正的自动化运维就是让自己"没事干"。
相关文章
版权声明
本文仅代表个人观点。
本文系AI辅助作者原创,未经许可,转载请保留原文链接。

发表评论