0

curl重定向监控脚本crontab配置详解:3个实战方案让网站跳转异常自动告警

2026.06.06 | youres | 25次围观

目录

  • 为什么需要用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
done

crontab配置

# 每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/health

crontab配置

# 每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.sh

crontab配置的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.com

2. 脚本路径要用绝对路径

crontab执行时的工作目录不一定是脚本所在目录。所有文件路径都要用绝对路径

# 错误写法
*/5 * * * * bash redirect_monitor.sh

# 正确写法
*/5 * * * * bash /opt/scripts/redirect_monitor.sh

3. 重定向输出日志

crontab默认不会把脚本的标准输出和错误输出记录下来。必须手动重定向到日志文件。

# 标准输出和错误都记录到日志
*/5 * * * * /opt/scripts/redirect_monitor.sh >> /var/log/monitor_cron.log 2>&1

4. 时间间隔的选择

根据业务重要性选择检测频率:

  • 核心业务页面:每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辅助作者原创,未经许可,转载请保留原文链接。

发表评论