2026.06.14 | youres | 8次围观
为什么要用curl批量检测网站状态码
做运维的都知道,网站挂了你不知道,比网站挂了本身更可怕。老板先于你发现网站打不开,那种尴尬谁经历谁懂。与其等用户投诉,不如自己写个脚本盯着——用curl批量检测网站HTTP状态码,一旦异常自动发邮件告警,这是最朴素也最有效的监控方案。
curl几乎每台Linux服务器都有,不需要装额外依赖;邮件告警不依赖第三方平台,不存在API限额问题。整套方案零成本、轻量级、部署快,适合中小规模网站监控。
方案一:基础串行检测+sendEmail告警
核心思路
从URL列表文件逐行读取网站地址,用curl获取HTTP状态码,连续失败3次则触发邮件告警。串行执行逻辑简单,适合监控10个以内的网站。
脚本代码
#!/bin/bash
# curl批量检测网站状态码+邮件告警
# 适合监控少量网站,串行检测
URL_FILE="/opt/urls.txt"
ADMIN_EMAIL="admin@example.com"
FAIL_THRESHOLD=3
LOG_FILE="/var/log/web_monitor.log"
check_url() {
local url=$1
local fail_count=0
for ((i=1; i<=FAIL_THRESHOLD; i++)); do
http_code=$(curl -o /dev/null --connect-timeout 5 -s -w "%{http_code}" "$url")
if [ "$http_code" -ge 200 ] && [ "$http_code" -lt 400 ]; then
echo "$(date '+%Y-%m-%d %H:%M:%S') $url OK ($http_code)" >> "$LOG_FILE"
return 0
fi
fail_count=$i
sleep 2
done
echo "$(date '+%Y-%m-%d %H:%M:%S') $url FAIL (code=$http_code, retry=$fail_count)" >> "$LOG_FILE"
send_alert "$url" "$http_code"
}
send_alert() {
local url=$1
local code=$2
local subject="[告警] 网站异常: $url"
local body="检测时间: $(date '+%Y-%m-%d %H:%M:%S')\n网站地址: $url\nHTTP状态码: $code\n连续失败次数: $FAIL_THRESHOLD\n请尽快排查处理。"
echo -e "$body" | mail -s "$subject" "$ADMIN_EMAIL"
}
# 主循环
while read -r url; do
[ -z "$url" ] && continue
check_url "$url"
done < "$URL_FILE"
URL列表文件格式
https://www.example.com
https://api.example.com
https://shop.example.com
部署要点
- 确保系统已安装mailx或postfix,否则mail命令无法发送
- curl的
--connect-timeout设5秒足够,太长会拖慢整体检测速度 - 2xx和3xx状态码都算正常,4xx和5xx才触发告警
方案二:并行检测+xargs加速
为什么需要并行
串行检测50个网站,每个超时5秒,最坏情况耗时250秒——快5分钟了。用xargs并行检测,50个网站10秒内出结果,效率提升20倍以上。
脚本代码
#!/bin/bash
# curl并行批量检测+邮件告警
# 适合监控大量网站
URL_FILE="/opt/urls.txt"
ADMIN_EMAIL="admin@example.com"
PARALLEL=10
LOG_FILE="/var/log/web_monitor.log"
ALERT_FILE="/tmp/web_alert_$(date +%s).txt"
check_single() {
local url=$1
local fail=0
for ((i=1; i<=3; i++)); do
http_code=$(curl -o /dev/null --connect-timeout 5 -s -w "%{http_code}" "$url")
if [ "$http_code" -ge 200 ] && [ "$http_code" -lt 400 ]; then
echo "$(date '+%Y-%m-%d %H:%M:%S') $url OK ($http_code)" >> "$LOG_FILE"
return 0
fi
fail=$i
sleep 1
done
echo "$(date '+%Y-%m-%d %H:%M:%S') $url FAIL (code=$http_code)" >> "$LOG_FILE"
echo "网站: $url | 状态码: $http_code | 时间: $(date '+%Y-%m-%d %H:%M:%S')" >> "$ALERT_FILE"
}
export -f check_single
export LOG_FILE ALERT_FILE
# 并行检测
cat "$URL_FILE" | grep -v '^$' | xargs -P $PARALLEL -I {} bash -c 'check_single "$@"' _ {}
# 批量发送告警邮件
if [ -f "$ALERT_FILE" ] && [ -s "$ALERT_FILE" ]; then
alert_count=$(wc -l < "$ALERT_FILE")
subject="[告警] ${alert_count}个网站检测异常"
{
echo "以下网站检测异常,请尽快处理:"
echo "================================"
cat "$ALERT_FILE"
echo "================================"
echo "检测时间: $(date '+%Y-%m-%d %H:%M:%S')"
} | mail -s "$subject" "$ADMIN_EMAIL"
rm -f "$ALERT_FILE"
fi
并行数选择建议
- 10个以内网站:串行即可,
PARALLEL=1 - 10-50个网站:
PARALLEL=10 - 50-200个网站:
PARALLEL=20 - 200个以上:考虑分批检测或用专业监控工具
方案三:crontab定时巡检+HTML格式邮件
核心思路
把检测脚本挂到crontab,每5分钟跑一次。邮件内容用HTML格式排版,包含正常和异常网站的完整状态表,一目了然。
脚本代码
#!/bin/bash
# 定时巡检+HTML格式邮件报告
# crontab: */5 * * * * /opt/web_monitor.sh
URL_FILE="/opt/urls.txt"
ADMIN_EMAIL="admin@example.com"
LOG_DIR="/var/log/web_monitor"
REPORT_FILE="$LOG_DIR/report_$(date +%Y%m%d_%H%M%S).html"
ALERT_ONLY=false # 设为true则只在异常时发邮件
mkdir -p "$LOG_DIR"
# 生成HTML报告头
cat > "$REPORT_FILE" << 'HEADER'
<!DOCTYPE html>
<html><head><meta charset="UTF-8">
<style>
body{font-family:Arial,sans-serif;margin:20px}
h2{color:#333;border-bottom:2px solid #4CAF50;padding-bottom:8px}
table{border-collapse:collapse;width:100%;margin-top:15px}
th{background:#4CAF50;color:white;padding:10px;text-align:left}
td{padding:8px 10px;border-bottom:1px solid #ddd}
.ok{color:#2e7d32;font-weight:bold}
.fail{color:#c62828;font-weight:bold}
.timestamp{color:#666;font-size:12px}
</style></head><body>
HEADER
echo "<h2>网站状态巡检报告</h2>" >> "$REPORT_FILE"
echo "<p class='timestamp'>检测时间: $(date '+%Y-%m-%d %H:%M:%S')</p>" >> "$REPORT_FILE"
echo "<table><tr><th>网站地址</th><th>状态码</th><th>状态</th><th>耗时</th></tr>" >> "$REPORT_FILE"
alert_list=""
while read -r url; do
[ -z "$url" ] && continue
start_time=$(date +%s%N)
http_code=$(curl -o /dev/null --connect-timeout 5 -s -w "%{http_code}" "$url")
end_time=$(date +%s%N)
elapsed=$(( (end_time - start_time) / 1000000 ))
if [ "$http_code" -ge 200 ] && [ "$http_code" -lt 400 ]; then
status_class="ok"
status_text="正常"
else
status_class="fail"
status_text="异常"
alert_list="${alert_list}${url} (HTTP ${http_code})\n"
fi
echo "<tr><td>${url}</td><td>${http_code}</td><td class='${status_class}'>${status_text}</td><td>${elapsed}ms</td></tr>" >> "$REPORT_FILE"
done < "$URL_FILE"
echo "</table></body></html>" >> "$REPORT_FILE"
# 判断是否需要发邮件
alert_count=$(echo -e "$alert_list" | grep -c '异常' 2>/dev/null || echo 0)
if [ "$ALERT_ONLY" = true ] && [ "$alert_count" -eq 0 ]; then
rm -f "$REPORT_FILE"
exit 0
fi
if [ "$alert_count" -gt 0 ]; then
subject="[告警] ${alert_count}个网站异常 - $(date '+%m-%d %H:%M')"
else
subject="[巡检] 全部网站正常 - $(date '+%m-%d %H:%M')"
fi
cat "$REPORT_FILE" | mail -s "$(echo '$subject' | iconv -t UTF-8)" \
-a "Content-Type: text/html; charset=UTF-8" "$ADMIN_EMAIL"
crontab配置
# 每5分钟检测一次
*/5 * * * * /opt/web_monitor.sh
# 每30分钟检测一次(非高峰期降低频率)
*/30 0-7 * * * /opt/web_monitor.sh
# 工作时间每5分钟,非工作时间每30分钟
*/5 8-23 * * 1-5 /opt/web_monitor.sh
*/30 0-7 * * * /opt/web_monitor.sh
3个方案对比总结
| 特性 | 方案一:串行 | 方案二:并行 | 方案三:定时+HTML |
|---|---|---|---|
| 适合网站数量 | 10个以内 | 50个以内 | 任意 |
| 检测速度 | 慢 | 快 | 中 |
| 邮件格式 | 纯文本 | 纯文本 | HTML表格 |
| 定时运行 | 需配合crontab | 需配合crontab | 内置 |
| 部署复杂度 | 低 | 中 | 中 |
| 告警策略 | 逐个发邮件 | 合并发邮件 | 按需发邮件 |
常见问题排查
mail命令发不出邮件
最常见的原因是系统没装邮件发送服务。CentOS装mailx和postfix,Ubuntu装mailutils。装完后用echo "test" | mail -s "test" your@email.com测试一下。
curl状态码为000
000不是HTTP状态码,而是curl自己返回的,表示连接超时或DNS解析失败。检查网络连通性和DNS配置,curl -v能看详细错误信息。
告警邮件太多导致疲劳
加入防抖机制:同一网站5分钟内只告警一次。可以用临时文件记录上次告警时间,脚本开头检查是否在冷却期内。
相关文章
版权声明
本文仅代表个人观点。
本文系AI辅助作者原创,未经许可,转载请保留原文链接。

发表评论