目录
- 为什么需要用curl做重定向监控
- 方案一:基础版crontab定时检测脚本
- 方案二:带日志轮转的高级监控方案
- 方案三:多URL批量监控+异常汇总推送
- crontab配置的5个关键细节
- 总结
为什么需要用curl做重定向监控
网站重定向出问题是运维中常见的隐形故障。你可能遇到这些情况:
- HTTPS证书过期导致重定向到错误页面
- CDN节点配置变更导致重定向次数暴增
- 服务器迁移后旧域名重定向链路断裂
- Nginx配置误操作引发重定向循环
这些问题如果靠人工发现,往往已经影响了大量用户。用curl配合crontab定时任务,可以实现7×24小时自动监控,重定向一有异常就能第一时间感知。
curl的优势在于:无需安装额外依赖、-w参数可以精确获取重定向次数和最终URL、输出格式可自定义,天然适合做监控探测。
方案一:基础版crontab定时检测脚本
这是最简单的入门方案,适合监控少量关键URL。核心思路:用curl的-w参数获取重定向信息,判断是否异常。
脚本代码
#!/bin/bash
# redirect_monitor.sh - 基础重定向监控脚本
# 监控的URL列表
URLS=(
"https://www.example.com"
"https://shop.example.com/product/1"
"https://blog.example.com/latest"
)
# 告警阈值:重定向次数超过此值则告警
MAX_REDIRECTS=5
LOG_FILE="/var/log/redirect_monitor.log"
ALERT_LOG="/var/log/redirect_alert.log"
for url in "${URLS[@]}"; do
# 使用curl -w获取重定向次数和最终URL
result=$(curl -o /dev/null -s -L -w "%{num_redirects}|%{url_effective}|%{http_code}|%{time_redirect}" --max-time 10 "$url" 2>&1)
num_redirects=$(echo "$result" | cut -d"|" -f1)
final_url=$(echo "$result" | cut -d"|" -f2)
http_code=$(echo "$result" | cut -d"|" -f3)
time_redirect=$(echo "$result" | cut -d"|" -f4)
echo "$(date "+%Y-%m-%d %H:%M:%S") | $url | redirects=$num_redirects final=$final_url code=$http_code time=${time_redirect}s" >> "$LOG_FILE"
# 判断是否异常
if [ "$num_redirects" -gt "$MAX_REDIRECTS" ]; then
echo "[ALERT] $(date "+%Y-%m-%d %H:%M:%S") 重定向次数过多: $url -> $num_redirects次跳转, 最终地址: $final_url" >> "$ALERT_LOG"
fi
if [ "$http_code" -ge 400 ]; then
echo "[ALERT] $(date "+%Y-%m-%d %H:%M:%S") HTTP错误: $url -> 状态码$http_code, 最终地址: $final_url" >> "$ALERT_LOG"
fi
donecrontab配置
# 每10分钟执行一次重定向检测
*/10 * * * * /opt/scripts/redirect_monitor.sh方案一适合的场景
- 监控URL数量在10个以内
- 只需要日志记录,不需要实时推送
- 对异常的容忍度较高(10分钟延迟可接受)
方案二:带日志轮转的高级监控方案
基础版有个问题:日志文件会无限增长。方案二加入了日志轮转、环境变量隔离和告警去重机制。
脚本代码
#!/bin/bash
# redirect_monitor_pro.sh - 高级重定向监控脚本(带日志轮转)
# ========== 配置区域 ==========
URLS_FILE="/opt/scripts/monitor_urls.txt"
MAX_REDIRECTS=5
MAX_TIME_REDIRECT=3.0
LOG_DIR="/var/log/redirect_monitor"
LOG_FILE="$LOG_DIR/monitor.log"
ALERT_LOG="$LOG_DIR/alert.log"
STATE_FILE="$LOG_DIR/last_alert_state.json"
ALERT_COOLDOWN=1800
# ========== 环境准备 ==========
export PATH="/usr/bin:/usr/local/bin:$PATH"
export LANG="en_US.UTF-8"
mkdir -p "$LOG_DIR"
# 日志轮转:超过50MB自动归档
if [ -f "$LOG_FILE" ] && [ $(stat -c%s "$LOG_FILE" 2>/dev/null || stat -f%z "$LOG_FILE") -gt 52428800 ]; then
mv "$LOG_FILE" "${LOG_FILE}.$(date +%Y%m%d%H%M%S).bak"
find "$LOG_DIR" -name "*.bak" -mtime +7 -delete
fi
# 检测逻辑
while IFS= read -r url; do
[[ -z "$url" || "$url" =~ ^# ]] && continue
result=$(curl -o /dev/null -s -L -w "%{num_redirects}|%{url_effective}|%{http_code}|%{time_redirect}" --max-time 15 "$url" 2>&1)
num_redirects=$(echo "$result" | cut -d"|" -f1)
final_url=$(echo "$result" | cut -d"|" -f2)
http_code=$(echo "$result" | cut -d"|" -f3)
time_redirect=$(echo "$result" | cut -d"|" -f4)
echo "$(date "+%Y-%m-%d %H:%M:%S") | $url | redirects=$num_redirects | code=$http_code | time=${time_redirect}s | final=$final_url" >> "$LOG_FILE"
alert_reason=""
if [ "$num_redirects" -gt "$MAX_REDIRECTS" ]; then
alert_reason="重定向次数过多($num_redirects次)"
fi
if [ "$(echo "$time_redirect > $MAX_TIME_REDIRECT" | bc -l 2>/dev/null || echo 0)" -eq 1 ]; then
alert_reason="重定向耗时过长(${time_redirect}s)"
fi
if [ "$http_code" -ge 400 ] 2>/dev/null; then
alert_reason="HTTP错误状态码($http_code)"
fi
if [ -n "$alert_reason" ]; then
url_hash=$(echo -n "$url" | md5sum | cut -d" " -f1)
now=$(date +%s)
last_alert=0
if [ -f "$STATE_FILE" ]; then
last_alert=$(grep "$url_hash" "$STATE_FILE" 2>/dev/null | tail -1 | cut -d"|" -f2 || echo 0)
fi
if [ $((now - last_alert)) -gt "$ALERT_COOLDOWN" ]; then
echo "[ALERT] $(date "+%Y-%m-%d %H:%M:%S") $url - $alert_reason - 最终: $final_url" >> "$ALERT_LOG"
echo "${url_hash}|${now}" >> "$STATE_FILE"
fi
fi
done < "$URLS_FILE"URL列表文件格式
# monitor_urls.txt - 每行一个URL,#开头为注释
https://www.example.com
https://shop.example.com/product/1
# API端点监控
https://api.example.com/v1/healthcrontab配置
# 每5分钟执行高级重定向检测
*/5 * * * * /opt/scripts/redirect_monitor_pro.sh >> /var/log/redirect_monitor/cron.log 2>&1
# 每天凌晨清理过期状态文件
0 3 * * * find /var/log/redirect_monitor -name "*.bak" -mtime +7 -delete方案三:多URL批量监控+异常汇总推送
方案三在方案二基础上增加了批量并发检测和异常汇总推送,适合运维团队使用。核心是用xargs -P实现并行请求,把所有结果汇总后一次性推送。
批量并发检测核心
#!/bin/bash
# redirect_batch_monitor.sh
URLS_FILE="/opt/scripts/monitor_urls.txt"
MAX_REDIRECTS=5
REPORT_FILE="/tmp/redirect_report_$(date +%Y%m%d_%H%M%S).txt"
# xargs并行检测,-P 10表示最多10个并发
cat "$URLS_FILE" | grep -v "^#" | grep -v "^$" | xargs -I{} -P 10 bash -c "
url="{}"
result=$(curl -o /dev/null -s -L -w "%{num_redirects}|%{url_effective}|%{http_code}|%{time_redirect}" --max-time 15 "$url" 2>&1)
echo "$url|$result"
" > "/tmp/redirect_raw_$$.txt"
# 分析并生成报告
echo "=== 重定向巡检报告 ===" > "$REPORT_FILE"
echo "检测时间: $(date "+%Y-%m-%d %H:%M:%S")" >> "$REPORT_FILE"
alert_count=0
while IFS="|" read -r url num_redir final code time_redir; do
is_alert=0
if [ "$num_redir" -gt "$MAX_REDIRECTS" ] 2>/dev/null; then
echo "[异常] $url -> 重定向${num_redir}次, 终点: $final" >> "$REPORT_FILE"
alert_count=$((alert_count + 1))
elif [ "$code" -ge 400 ] 2>/dev/null; then
echo "[异常] $url -> HTTP $code, 终点: $final" >> "$REPORT_FILE"
alert_count=$((alert_count + 1))
fi
done < "/tmp/redirect_raw_$$.txt"
[ "$alert_count" -eq 0 ] && echo "全部正常" >> "$REPORT_FILE"
rm -f "/tmp/redirect_raw_$$.txt"crontab配置
# 每30分钟执行批量巡检
*/30 * * * * /opt/scripts/redirect_batch_monitor.sh
# 每天早上8点发送日报
0 8 * * * /opt/scripts/redirect_batch_monitor.shcrontab配置的5个关键细节
很多同学的监控脚本写好了,但crontab执行时总出问题。这5个细节必须注意:
1. 环境变量问题
crontab的执行环境和你手动执行脚本的环境完全不同。PATH变量可能不包含curl所在的路径,导致"command not found"。
# 在脚本开头显式设置PATH
export PATH="/usr/bin:/usr/local/bin:$PATH"
# 或者在crontab中指定完整路径
*/5 * * * * /usr/bin/curl -o /dev/null -s -L -w "..." https://example.com2. 脚本路径要用绝对路径
crontab执行时的工作目录不一定是脚本所在目录。所有文件路径都要用绝对路径。
# 错误写法
*/5 * * * * bash redirect_monitor.sh
# 正确写法
*/5 * * * * bash /opt/scripts/redirect_monitor.sh3. 重定向输出日志
crontab默认不会把脚本的标准输出和错误输出记录下来。必须手动重定向到日志文件。
# 标准输出和错误都记录到日志
*/5 * * * * /opt/scripts/redirect_monitor.sh >> /var/log/monitor_cron.log 2>&14. 时间间隔的选择
根据业务重要性选择检测频率:
- 核心业务页面:每5分钟(*/5 * * * *)
- 一般页面:每15-30分钟
- 静态资源CDN:每小时
5. 避免任务重叠执行
如果上一次脚本还没跑完,crontab又触发了一次,会导致日志混乱或重复告警。使用锁文件机制防止重叠:
#!/bin/bash
LOCK_FILE="/tmp/redirect_monitor.lock"
exec 200>"$LOCK_FILE"
flock -n 200 || exit 0 # 获取锁失败则退出总结
用curl配合crontab做重定向监控,本质上是把人工检查自动化。三个方案从简单到复杂,覆盖了不同的运维需求:
- 方案一:快速上手,适合个人站长监控少量关键URL
- 方案二:带日志轮转和告警冷却,适合长期运行的监控
- 方案三:批量并发+汇总推送,适合运维团队规模化监控
记住crontab的5个关键细节——环境变量、绝对路径、日志重定向、频率选择、锁文件——能帮你避开90%的坑。监控不是一劳永逸的事,定期检查告警日志、调整URL列表和阈值,才能让监控真正发挥作用。
相关推荐
版权声明
本文仅代表个人观点。
本文系AI辅助作者原创,未经许可,转载请保留原文链接。

发表评论