0

curl批量检测HTTP状态码输出CSV报告:3个实战脚本让网站巡检结果一目了然

2026.06.15 | youres | 9次围观

为什么要批量检测HTTP状态码并输出CSV

网站数量多了,手动一个个curl检查状态码不现实。把检测结果输出为CSV文件,有几个明显好处:

  • Excel直接打开——CSV格式通用,双击就能用Excel查看,还能排序、筛选、做图表
  • 存档追溯——每次巡检生成一份CSV,历史数据可对比,网站什么时候开始异常一目了然
  • 对接告警——CSV文件可以被其他脚本读取,自动判断异常并发送告警

下面给出3个实战脚本,从简单到进阶,覆盖绝大多数使用场景。

脚本一:串行检测输出CSV

最基础的方案,逐个检测URL的状态码,结果写入CSV文件。适合网站数量不多(50个以内)的场景。

#!/bin/bash
# curl批量检测HTTP状态码输出CSV报告
# 用法: bash check_status_csv.sh urls.txt

URL_FILE=${1:-urls.txt}
CSV_FILE="status_report_$(date +%Y%m%d_%H%M%S).csv"

# 写CSV表头
echo "URL,HTTP状态码,响应时间(秒),检测时间" > "$CSV_FILE"

while IFS= read -r url; do
    # 跳过空行和注释
    [[ -z "$url" || "$url" == \#* ]] && continue

    # 获取状态码和响应时间
    result=$(curl -o /dev/null -s -w "%{http_code} %{time_total}" \
        --connect-timeout 5 --max-time 10 "$url")

    http_code=$(echo "$result" | awk '{print $1}')
    time_total=$(echo "$result" | awk '{print $2}')
    check_time=$(date "+%Y-%m-%d %H:%M:%S")

    echo "$url,$http_code,$time_total,$check_time" >> "$CSV_FILE"
    echo "检测: $url -> $http_code (${time_total}s)"
done < "$URL_FILE"

echo "报告已生成: $CSV_FILE"
echo "异常URL统计:"
awk -F',' 'NR>1 && $2!=200 {print $1 " -> " $2}' "$CSV_FILE"

urls.txt文件格式(一行一个URL):

https://www.baidu.com
https://www.qq.com
https://www.taobao.com
https://nonexistent.example.com

输出效果

URL,HTTP状态码,响应时间(秒),检测时间
https://www.baidu.com,200,0.052,2026-06-15 01:00:01
https://www.qq.com,200,0.038,2026-06-15 01:00:02
https://www.taobao.com,200,0.121,2026-06-15 01:00:03
https://nonexistent.example.com,000,5.001,2026-06-15 01:00:08

状态码000表示连接超时或无法建立连接,脚本已经用--connect-timeout 5限制了等待时间。

脚本二:xargs并行加速检测

串行检测在URL数量多的时候很慢,100个网站可能要跑好几分钟。用xargs -P并行执行,速度能提升好几倍。

#!/bin/bash
# curl并行批量检测HTTP状态码输出CSV报告
# 用法: bash check_status_parallel.sh urls.txt [并发数]

URL_FILE=${1:-urls.txt}
PARALLEL=${2:-10}
CSV_FILE="status_report_$(date +%Y%m%d_%H%M%S).csv"
TMP_DIR="/tmp/curl_check_$$"

mkdir -p "$TMP_DIR"

# 写CSV表头
echo "URL,HTTP状态码,响应时间(秒),检测时间" > "$CSV_FILE"

# 单个URL检测函数
check_url() {
    local url="$1"
    local tmp_file="$TMP_DIR/$(echo "$url" | md5sum | cut -c1-8)"

    result=$(curl -o /dev/null -s -w "%{http_code} %{time_total}" \
        --connect-timeout 5 --max-time 10 "$url")

    http_code=$(echo "$result" | awk '{print $1}')
    time_total=$(echo "$result" | awk '{print $2}')
    check_time=$(date "+%Y-%m-%d %H:%M:%S")

    echo "$url,$http_code,$time_total,$check_time" > "$tmp_file"
}

# 导出函数供xargs使用
export -f check_url
export TMP_DIR

# 并行执行检测
grep -v '^#' "$URL_FILE" | grep -v '^$' | xargs -P "$PARALLEL" -I {} bash -c 'check_url "$@"' _ {}

# 合并结果到CSV
cat "$TMP_DIR"/* >> "$CSV_FILE" 2>/dev/null

# 清理临时文件
rm -rf "$TMP_DIR"

# 统计结果
total=$(tail -n +2 "$CSV_FILE" | wc -l)
ok_count=$(tail -n +2 "$CSV_FILE" | awk -F',' '$2==200' | wc -l)
fail_count=$((total - ok_count))

echo "报告已生成: $CSV_FILE"
echo "检测总数: $total | 正常: $ok_count | 异常: $fail_count"

# 输出异常URL
if [ "$fail_count" -gt 0 ]; then
    echo ""
    echo "异常URL列表:"
    tail -n +2 "$CSV_FILE" | awk -F',' '$2!=200 {print $1 " -> 状态码:" $2}'
fi

使用方式

# 默认10个并发
bash check_status_parallel.sh urls.txt

# 指定20个并发
bash check_status_parallel.sh urls.txt 20

并发数不是越大越好。一般建议设为10-20,太大了可能触发目标服务器的限频,或者把本机网络带宽跑满。

并行方案的注意事项

  • 并发数控制:根据目标服务器承受能力和本机性能调整,一般10-20即可
  • 结果顺序:并行执行时各URL完成顺序不确定,CSV中URL顺序和输入文件可能不一致
  • 临时文件:脚本用/tmp存放中间结果,执行完自动清理;如果中途Ctrl+C,可能残留临时文件
  • md5命名:用URL的md5前8位作为临时文件名,避免特殊字符出问题

脚本三:crontab定时巡检自动生成CSV

把巡检脚本放到crontab里定时跑,每天自动生成一份CSV报告,再也不用手动执行。

#!/bin/bash
# 定时巡检脚本: daily_status_check.sh
# crontab配置: 0 8 * * * /path/to/daily_status_check.sh

URL_FILE="/path/to/urls.txt"
REPORT_DIR="/path/to/reports"
PARALLEL=10

# 按日期命名CSV
DATE=$(date +%Y%m%d)
CSV_FILE="$REPORT_DIR/daily_status_${DATE}.csv"
ALERT_LOG="$REPORT_DIR/alert_${DATE}.log"

mkdir -p "$REPORT_DIR"

# 写CSV表头
echo "URL,HTTP状态码,响应时间(秒),检测时间" > "$CSV_FILE"

# 检测函数
check_url() {
    local url="$1"
    result=$(curl -o /dev/null -s -w "%{http_code} %{time_total}" \
        --connect-timeout 5 --max-time 10 "$url")
    http_code=$(echo "$result" | awk '{print $1}')
    time_total=$(echo "$result" | awk '{print $2}')
    check_time=$(date "+%Y-%m-%d %H:%M:%S")
    echo "$url,$http_code,$time_total,$check_time"
}

# 并行检测并写入CSV
while IFS= read -r url; do
    [[ -z "$url" || "$url" == \#* ]] && continue
    check_url "$url" &
done < "$URL_FILE" >> "$CSV_FILE"

wait

# 检查异常并记录告警日志
awk -F',' 'NR>1 && $2!=200 && $2!=301 && $2!=302' "$CSV_FILE" > "$ALERT_LOG"

# 如果有异常,输出告警信息
if [ -s "$ALERT_LOG" ]; then
    alert_count=$(wc -l < "$ALERT_LOG")
    echo "[$(date)] 发现 ${alert_count} 个异常URL" >> "$REPORT_DIR/alert_history.log"
fi

# 清理30天前的报告
find "$REPORT_DIR" -name "*.csv" -mtime +30 -delete
find "$REPORT_DIR" -name "*.log" -mtime +30 -delete

echo "巡检完成: $CSV_FILE"

crontab配置

# 每天早上8点执行巡检
0 8 * * * /path/to/daily_status_check.sh

这个脚本有几个实用细节:

  • 301/302不算异常——重定向是正常行为,不算故障
  • 30天自动清理——老报告自动删除,不会把磁盘撑满
  • 告警日志单独存放——方便对接后续的告警通知

CSV报告的后续利用

1. Excel可视化分析

用Excel打开CSV后,可以做条件格式:状态码非200的标红,响应时间超过2秒的标黄。一眼就能看出哪些网站有问题。

2. 历史趋势对比

把多天的CSV文件合并,用Excel做数据透视表,看每个URL的响应时间趋势。如果某个URL响应时间持续增长,可能需要提前介入。

3. 对接告警系统

CSV文件可以被Python脚本或Shell脚本读取,发现异常后自动调用钉钉机器人、企业微信Webhook或邮件发送告警。

常见问题

状态码000是什么意思?

000不是HTTP标准状态码,是curl自己返回的,表示连接失败。常见原因:DNS解析失败、连接超时、网络不通。脚本里已经用--connect-timeout控制了超时时间。

CSV文件用Excel打开中文乱码怎么办?

Shell脚本输出的CSV默认是UTF-8编码,Excel打开可能乱码。两个解决方法:

  • 在CSV文件开头加BOM头:printf '\xEF\xBB\xBF' > $CSV_FILE,然后追加内容
  • 用Excel的"数据"→"从文本/CSV"导入,手动选择UTF-8编码

并行检测时结果顺序乱了怎么办?

并行方案结果顺序确实会乱。如果需要按原始URL顺序排列,可以在合并结果后用sort命令排序,或者在脚本里记录URL的行号,最后按行号排序。

相关文章

版权声明

本文仅代表个人观点。
本文系AI辅助作者原创,未经许可,转载请保留原文链接。

发表评论