做网站运维的都逃不过一个问题——批量检测重定向。几十上百个URL需要定期巡检,结果怎么存?CSV太原始,HTML报告太重,JSON才是最灵活的选择。今天聊聊怎么用curl的-w参数配合JSON模板,把重定向检测结果结构化输出。
为什么JSON比CSV更适合重定向巡检
CSV的问题在于:重定向链路这种嵌套数据不好表达。一个URL可能经过3跳,每跳有状态码、Location头、耗时,CSV要么挤成一行超长字符串,要么拆成多行关联查询很麻烦。
JSON天然支持嵌套结构,一个URL的所有检测数据可以打包成一个对象,数组存多个URL的结果,jq一行命令就能过滤分析。更重要的是,JSON可以直接对接后续的数据处理——导入数据库、喂给监控平台、API推送,都比CSV顺畅。
方案一:curl -w单行JSON模板
最直接的方式是用curl -w把结果格式化成单行JSON。核心思路是手动拼接JSON字段:
# 检测单个URL的重定向结果,输出JSON
curl -s -o /dev/null -w '{"url":"%{url_effective}","redirects":%{num_redirects},"http_code":%{http_code},"time_total":%{time_total},"time_redirect":%{time_redirect},"remote_ip":"%{remote_ip}"}\n' \
-L "https://example.com"
输出示例:
{"url":"https://example.com/final-page","redirects":2,"http_code":200,"time_total":0.543,"time_redirect":0.231,"remote_ip":"93.184.216.34"}
几个注意点:
- 字段值如果是字符串要用引号包裹,数字类型不加引号
- \n在模板里是换行符,确保每个URL一行
- 用-s -o /dev/null静默主体内容,只输出-w的格式化结果
- 配合jq美化输出:curl ... | jq .
批量检测脚本
#!/bin/bash
# 批量检测重定向并输出JSON数组
URLS_FILE="urls.txt"
echo "[" > result.json
first=true
while IFS= read -r url; do
[ -z "" ] && continue
if [ "" = true ]; then
first=false
else
echo "," >> result.json
fi
curl -s -o /dev/null -w '{"original":"'url'","final":"%{url_effective}","redirects":%{num_redirects},"code":%{http_code},"time":%{time_total}}' \
-L --max-time 10 "" >> result.json
done < ""
echo "]" >> result.json
这段脚本读取urls.txt中的URL列表,逐个检测后把结果拼接成合法的JSON数组。用jq校验一下:jq . result.json
方案二:curl -w @模板文件方式
当检测字段多的时候,命令行拼字符串容易出错。curl支持-w @文件从文件读取模板,更清晰:
创建模板文件redirect.json.tpl:
{
"original_url": "https://www.example.com",
"final_url": "%{url_effective}",
"redirect_count": %{num_redirects},
"http_code": %{http_code},
"response": {
"dns_time": %{time_namelookup},
"connect_time": %{time_connect},
"redirect_time": %{time_redirect},
"total_time": %{time_total}
},
"ssl": {
"verify_result": %{ssl_verify_result}
}
}
使用方式:
curl -s -o /dev/null -w @redirect.json.tpl -L "https://example.com"
用sed动态替换URL字段
模板里original_url是固定的,实际使用时需要动态替换。简单做法是用sed:
# 生成动态模板
sed "s|https://www.example.com|url|g" redirect.json.tpl > /tmp/dyn_tpl.txt
curl -s -o /dev/null -w @/tmp/dyn_tpl.txt -L "url"
完整批量脚本:
#!/bin/bash
TPL="redirect.json.tpl"
URLS="urls.txt"
OUT="redirect_report_(date +%Y%m%d).json"
echo "[" > "OUT"
first=true
while IFS= read -r url; do
[ -z "url" ] &&& continue
[ "first" = true ] &&& first=false || echo "," >> "OUT"
sed "s|https://www.example.com|url|g" "TPL" > /tmp/dyn.tpl
result=(curl -s -o /dev/null -w @/tmp/dyn.tpl -L --max-time 10 "url" 2>/dev/null)
echo "result" >> "OUT"
done < "URLS"
echo "]" >> "OUT"
rm -f /tmp/dyn.tpl
echo "报告已生成: OUT"
这个方案的优点是模板可维护、字段清晰,缺点是sed替换有注入风险——URL如果含特殊字符可能破坏JSON结构。实际生产环境建议对URL做JSON转义预处理。
方案三:混合输出+jq后处理
如果不想在curl模板里硬拼JSON结构,更稳妥的方式是curl输出原始格式化数据,然后用jq组装:
# curl输出TSV格式,jq转JSON
curl -s -o /dev/null \
-w "%{url_effective}\t%{num_redirects}\t%{http_code}\t%{time_total}\t%{time_redirect}\n" \
-L "https://example.com" | \
jq -Rsn '
[inputs | split("\t") | .[] | select(length > 0) |
. as row |
{
final_url: row[0],
redirects: (row[1] | tonumber),
http_code: (row[2] | tonumber),
total_time: (row[3] | tonumber),
redirect_time: (row[4] | tonumber)
}
]'
批量版本:
#!/bin/bash
OUT="redirect_report.json"
curl -s -o /dev/null \
-w "%{url_effective}\t%{num_redirects}\t%{http_code}\t%{time_total}\t%{time_redirect}\n" \
-L --max-time 10 -K urls.txt | \
jq -Rsn '
[inputs | split("\t") | .[] | select(length > 0) |
. as row |
{
final_url: row[0],
redirects: (row[1] | tonumber),
http_code: (row[2] | tonumber),
total_time: (row[3] | tonumber),
redirect_time: (row[4] | tonumber)
}
]' > "OUT"
注意-K参数读取URL列表的格式是url = "https://xxx",每个URL一行。这种方式的好处是JSON结构完全由jq控制,不受curl模板限制,不容易出格式错误。
常用curl -w变量速查
重定向检测中常用的-w变量:
- url_effective - 最终跳转后的URL
- num_redirects - 重定向次数
- http_code - 最终HTTP状态码
- redirect_url - 查询重定向到的URL(不跟随重定向时使用)
- time_total - 总耗时(秒)
- time_redirect - 重定向耗时
- time_namelookup - DNS解析耗时
- time_connect - TCP连接耗时
- ssl_verify_result - SSL证书验证结果(0为通过)
- remote_ip - 目标服务器IP
实用技巧
1. 并行加速:加xargs -P并行:
xargs -P 10 -I {} curl -s -o /dev/null \
-w '{"url":"%{url_effective}","code":%{http_code}}\n' \
-L --max-time 10 {} < urls.txt
2. 异常过滤:用jq筛选有问题的URL:
# 找出状态码非200的
jq '[.[] | select(.http_code != 200)]' result.json
# 找出重定向次数超过3的
jq '[.[] | select(.redirects > 3)]' result.json
# 找出耗时超过2秒的
jq '[.[] | select(.total_time > 2)]' result.json
3. 超时保护:批量检测一定要加--max-time,避免个别慢站点卡住整个脚本。建议设10秒。
总结
三种方案各有适用场景:单行JSON模板适合简单快速检测,@模板文件方式适合字段多且需要维护的场景,混合输出+jq后处理最稳健适合生产环境。选哪个看你的巡检规模和数据处理需求——但不管选哪个,JSON格式化存储都是让重定向巡检数据真正有用的关键一步。
相关阅读
版权声明
本文仅代表个人观点。
本文系AI辅助作者原创,未经许可,转载请保留原文链接。

发表评论