前言
做网站运维,少不了要批量检测一堆URL的状态。HTTP跳转正不正常、证书什么时候到期、某个接口响应快不快——这些问题靠浏览器一个个点,根本不现实。用Shell脚本配合curl,几行代码就能把重复劳动自动化。今天分享4种从简单到高级的批量请求方法,覆盖日常巡检的各个场景。
一、基础循环:for 和 while 两种写法
1.1 for 循环处理URL列表
最基础的写法,直接把URL写死在脚本里或者从文件读取:
# 直接写URL
for url in https://site-a.com https://site-b.com https://site-c.com; do
echo "检测: $url"
curl -o /dev/null -s -w "状态码:%{http_code} 耗时:%{time_total}s\n" "$url"
done加上重定向检测(-L 跟随跳转,-s 静默):
for url in https://site-a.com https://site-b.com; do
result=$(curl -o /dev/null -s -w "%{http_code}|%{time_total}|%{url_effective}" -L "$url")
echo "$url -> $result"
done1.2 while read 逐行读取文件
URL多的时候不适合写死在脚本里,存成文件一行一个,读取处理更灵活:
# urls.txt 每行一个URL
while IFS= read -r url; do
status=$(curl -o /dev/null -s -w "%{http_code}" -L "$url")
echo "$url | $status"
done < urls.txt配合awk提取响应时间和状态码,做简单格式化:
while IFS= read -r url; do
curl -o /dev/null -s -w "$url %{http_code} %{time_total}s\n" -L "$url"
done < urls.txt | awk '{print NR"|"$0}'二、并行加速:让批量请求快10倍
顺序执行有个明显问题——10个URL每个耗时2秒,总共要等20秒。实际工作中经常要检测几十上百个域名,串行太慢了。并行处理能显著缩短总耗时。
2.1 xargs 并行
# 读取URL文件,4个并行执行
cat urls.txt | xargs -P 4 -I {} \
bash -c 'url={}; status=$(curl -o /dev/null -s -w "%{http_code}" "$url"); echo "$url|$status"'实用示例:批量检测状态码,超时控制10秒:
cat urls.txt | xargs -P 8 -I {} \
bash -c 'url={}; status=$(curl -o /dev/null -s -w "%{http_code}" --connect-timeout 5 --max-time 10 "$url"); echo "$url|$status"' > status_results.txt2.2 GNU Parallel(更强大)
# 安装:apt install parallel 或 yum install parallel
# 20个并行,--dry-run 先预览要执行什么命令
cat urls.txt | parallel -P 20 --dry-run 'curl -s -o /dev/null -w "%{url_effective}|%{http_code}|%{time_total}\n" {}'去掉 --dry-run 实际执行:
# 实际运行:20并发,输出到结果文件
cat urls.txt | parallel -P 20 'curl -s -o /dev/null -w "%{url_effective}|%{http_code}|%{time_total}\n" {}' > results.txt两者区别:xargs 是 GNU coreutils 自带的,大多数Linux系统直接可用;Parallel 需要单独安装,但支持更丰富的参数,如内存控制、任务控制、进度显示。巡检50个以内域名用 xargs 完全够用,超过100个域名建议上 Parallel。
三、输出格式化:让结果更易读
3.1 日志追加
log_batch() {
local url=$1
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
local result=$(curl -o /dev/null -s -w "%{http_code}|%{time_total}|%{url_effective}" -L "$url")
echo "$timestamp|$url|$result" >> batch_result.log
}
while IFS= read -r url; do
log_batch "$url"
done < urls.txt
echo "检测完成,共 $(wc -l < urls.txt) 个URL"3.2 CSV 导出(Excel 直接打开)
# PowerShell 版:批量检测状态码并导出 CSV
$urls = @(
'https://www.youres.cn',
'https://httpbin.org/status/200',
'https://httpbin.org/status/404'
)
$results = @()
foreach ($url in $urls) {
try {
$r = Invoke-WebRequest -Uri $url -MaximumRedirection 5 -TimeoutSec 10 -ErrorAction Stop
$results += [PSCustomObject]@{
URL = $url
StatusCode = $r.StatusCode
FinalURL = $r.BaseResponse.ResponseUri
ResponseTime = [math]::Round(($r.Elapsed.TotalMilliseconds)/1000, 3)
}
} catch {
$results += [PSCustomObject]@{
URL = $url
StatusCode = "ERROR"
FinalURL = $_.Exception.Message
ResponseTime = -1
}
}
}
$results | Export-Csv -Path results.csv -NoTypeInformation -Encoding UTF8四、错误处理:让脚本更健壮
网络请求不可避免会遇到各种异常——DNS解析失败、连接超时、SSL证书问题。做好容错,脚本才能真正用于生产环境。
4.1 curl 退出码判断
check_url() {
local url=$1
# curl 退出码含义:
# 0 - 成功(含4xx/5xx HTTP响应)
# 22 - HTTP 4xx/5xx(服务器返回了错误页面)
# 28 - 连接超时
# 7 - 连接失败(服务器不可达)
local output=$(curl -o /dev/null -s -w "%{http_code}|%{time_total}|%{url_effective}" \
--connect-timeout 5 --max-time 15 -L "$url" 2>&1)
local exit_code=$?
if [ $exit_code -eq 0 ]; then
echo "OK|$output"
elif [ $exit_code -eq 28 ]; then
echo "TIMEOUT|$url"
elif [ $exit_code -eq 7 ]; then
echo "CONN_FAIL|$url"
else
echo "ERROR|exit_$exit_code|$url"
fi
}
# 处理结果:只告警非正常状态的
while IFS= read -r url; do
result=$(check_url "$url")
status=$(echo "$result" | awk -F'|' '{print $2}')
if [ "$status" != "200" ] && [ "$status" != "301" ] && [ "$status" != "302" ]; then
echo "告警: $url 状态 -> $result"
fi
done < urls.txt4.2 超时与重试机制
curl_retry() {
local url=$1
local max_try=3
local try=0
while [ $try -lt $max_try ]; do
try=$((try+1))
status=$(curl -o /dev/null -s -w "%{http_code}" \
--connect-timeout 5 --max-time 10 "$url" 2>/dev/null)
if [ $? -eq 0 ]; then
echo "$url|$status"
return 0
fi
echo "第${try}次失败,重试中..." >&2
sleep 2
done
echo "$url|FAIL_AFTER_${max_try}_TRIES"
return 1
}五、性能优化:让脚本跑得更快
同样是批量请求,细节不同速度能差好几倍。
5.1 超时设置要合理
--connect-timeout 5 --max-time 15:连接超时5秒、总超时15秒。兼顾了速度和容错,不设超时的话一个卡住的请求会拖垮整个脚本。
5.2 静默模式
-s 静默模式关闭进度条和错误输出,减少终端I/O开销。对脚本批量执行尤为重要。
5.3 并行数的选择
并行50和并行100测同一个网站,可能后者反而更慢——并发太多会导致服务器限流或本地端口耗尽。建议从并行10-20开始测试,观察响应时间是否稳定后再调整。
5.4 只获取响应头
如果只需要检查状态,不需要完整响应体,用 -I 或 --head 只发 HEAD 请求,速度更快、服务器压力更小:
cat urls.txt | xargs -P 10 -I {} \
bash -c 'curl -I -s -o /dev/null -w "%{http_code}|%{time_total}|{}\n" --connect-timeout 5 --max-time 10 {}'六、总结
Shell脚本配合curl做批量请求是运维工作中非常实用的技能。核心要点:
- 顺序执行:用
for或while read逐条处理,适合调试和小批量场景 - 并行加速:
xargs -P或GNU Parallel,10个URL从20秒压缩到2-3秒 - 输出格式化:加时间戳、状态码、响应时间,结果存入日志或CSV
- 错误处理:检查curl退出码,超时和连接失败要单独处理
- 性能调优:合理超时、静默模式、HEAD请求、并行数适中
掌握了这些技巧,无论是日常网站巡检、证书监控,还是批量重定向检测,都能用几行Shell脚本搞定。
版权声明
本文仅代表个人观点。
本文系AI辅助作者原创,未经许可,转载请保留原文链接。

发表评论