HTTP 定时监控脚本

112 阅读2分钟

在进行站点 LB 切换时,为了确保切换过程中不会出现异常响应,可以通过脚本模拟用户请求并记录状态码进行监控。脚本 monitor_http.sh 允许用户自定义检查频率、总监控时间、请求超时时间和目标 URL。脚本会记录每次请求的时间戳、状态码、响应时间和错误信息,并生成错误日志和详细日志。监控结束后,脚本会输出总监控时长、请求次数、错误次数、错误率以及响应时间的统计信息。通过这种方式,可以实时观察站点在 LB 切换过程中的表现,确保切换顺利进行。

使用说明

  1. 将脚本保存为文件,例如 monitor_http.sh
  2. 添加执行权限:chmod +x monitor_http.sh
  3. 运行脚本:./monitor_http.sh

自定义选项

根据需要,可以调整以下参数:

  • CHECK_INTERVAL:检查频率(秒),值越小检查越频繁
  • TOTAL_DURATION:总监控时间(秒),设置为您计划服务重启的时间范围
  • CURL_TIMEOUT:单次请求超时时间,防止卡住
  • URL:监控的目标 URL

脚本内容如下:

#!/bin/bash

# 配置参数
URL="https://www.baidu.com"
CHECK_INTERVAL=0.5  # 检查间隔(秒)
LOG_FILE="http_availability_$(date +%Y%m%d_%H%M%S).log"
DETAILED_LOG_FILE="http_detailed_$(date +%Y%m%d_%H%M%S).log"
TOTAL_DURATION=300  # 总监控时间(秒),设为5分钟
CURL_TIMEOUT=5      # curl 超时时间(秒)

echo "开始监控 $URL" | tee -a "$LOG_FILE"
echo "监控时间: $(date)" | tee -a "$LOG_FILE"
echo "检查间隔: ${CHECK_INTERVAL}秒" | tee -a "$LOG_FILE"
echo "日志文件: $LOG_FILE (错误日志)" | tee -a "$LOG_FILE"
echo "详细日志: $DETAILED_LOG_FILE (所有请求)" | tee -a "$LOG_FILE"
echo "-----------------------------------" | tee -a "$LOG_FILE"

# 创建详细日志的表头
echo "时间戳,状态码,响应时间(秒),错误信息" > "$DETAILED_LOG_FILE"

start_time=$(date +%s)
request_count=0
error_count=0
total_response_time=0
max_response_time=0
min_response_time=999999

# 捕获 CTRL+C 信号
trap 'echo -e "\n监控被用户中断" | tee -a "$LOG_FILE"; print_summary; exit' INT

print_summary() {
    end_time=$(date +%s)
    duration=$((end_time - start_time))
    echo "-----------------------------------" | tee -a "$LOG_FILE"
    echo "监控结束时间: $(date)" | tee -a "$LOG_FILE"
    echo "总监控时长: ${duration}秒" | tee -a "$LOG_FILE"
    echo "请求总次数: $request_count" | tee -a "$LOG_FILE"
    echo "错误总次数: $error_count" | tee -a "$LOG_FILE"
    
    if [ $request_count -gt 0 ]; then
        error_rate=$(echo "scale=4; $error_count * 100 / $request_count" | bc)
        echo "错误率: ${error_rate}%" | tee -a "$LOG_FILE"
        
        if [ $request_count -gt $error_count ]; then
            avg_response_time=$(echo "scale=4; $total_response_time / ($request_count - $error_count)" | bc)
            echo "平均响应时间: ${avg_response_time}秒" | tee -a "$LOG_FILE"
            echo "最大响应时间: ${max_response_time}秒" | tee -a "$LOG_FILE"
            echo "最小响应时间: ${min_response_time}秒" | tee -a "$LOG_FILE"
        fi
    fi
    
    echo "详细请求日志保存在: $DETAILED_LOG_FILE" | tee -a "$LOG_FILE"
}

# 主循环
while true; do
    current_time=$(date +%s)
    if [ $((current_time - start_time)) -ge $TOTAL_DURATION ]; then
        echo "达到预设监控时间 ${TOTAL_DURATION}秒,监控结束" | tee -a "$LOG_FILE"
        print_summary
        exit 0
    fi

    timestamp=$(date "+%Y-%m-%d %H:%M:%S.%3N")
    request_count=$((request_count + 1))
    
    # 临时文件保存 curl 输出
    temp_file=$(mktemp)
    start_request=$(date +%s.%N)
    
    # 使用 curl 检查状态码和响应时间
    status_code=$(curl -s -o "$temp_file" -w "%{http_code}" -m "$CURL_TIMEOUT" "$URL" 2>/dev/null)
    curl_exit_code=$?
    end_request=$(date +%s.%N)
    
    # 计算响应时间
    response_time=$(echo "$end_request - $start_request" | bc)
    error_msg=""
    
    # 检查 curl 是否成功
    if [ $curl_exit_code -ne 0 ]; then
        error_count=$((error_count + 1))
        case $curl_exit_code in
            7) error_msg="连接失败" ;;
            28) error_msg="请求超时" ;;
            *) error_msg="curl错误:$curl_exit_code" ;;
        esac
        echo "[$timestamp] 请求失败: $error_msg" | tee -a "$LOG_FILE"
    elif [ "$status_code" != "200" ]; then
        error_count=$((error_count + 1))
        error_msg="状态码:$status_code"
        echo "[$timestamp] 检测到异常状态码: $status_code" | tee -a "$LOG_FILE"
    else
        # 更新响应时间统计
        total_response_time=$(echo "$total_response_time + $response_time" | bc)
        if (( $(echo "$response_time > $max_response_time" | bc -l) )); then
            max_response_time=$response_time
        fi
        if (( $(echo "$response_time < $min_response_time" | bc -l) )); then
            min_response_time=$response_time
        fi
    fi
    
    # 写入详细日志
    echo "$timestamp,$status_code,$response_time,\"$error_msg\"" >> "$DETAILED_LOG_FILE"
    
    # 清理临时文件
    rm -f "$temp_file"
    
    sleep $CHECK_INTERVAL
done