Bash执行变量存储的cURL请求时如何记录成功与失败URL
问题根因
原脚本无法正确记录失败请求,是4个核心问题导致的:
- 逻辑判断绑定错误:
&&/||是左结合同优先级运算符,原脚本把grep提取URL的执行结果和curl请求的结果混在同一条判断链里——哪怕curl请求成功,只要grep没匹配到URL(比如目标是zip后缀不是html),就会错误触发失败分支;反过来如果curl执行失败但grep意外匹配到字符串,也会误写到成功日志。 - URL提取正则不匹配:原正则
http.*html只匹配带.html后缀的地址,示例里的url.zip、接口类无后缀地址、其他静态资源地址完全匹配不到,grep返回空值自然写不进日志。 - 循环写法存在解析缺陷:用
for f in $(echo $var)的写法,会按空白字符拆分内容,只要curl命令里带空格、转义符、引号,就会把单条完整curl命令拆成多段,直接执行报错。 - curl未开启错误状态识别:默认curl只要收到服务器响应(哪怕返回404、500、403错误状态)都会返回0退出码,根本识别不了HTTP层面的请求失败。
修正方案
按以下逻辑调整脚本即可:
- 给curl增加
-f参数,让HTTP 4xx/5xx错误时返回非0退出码,正确识别请求失败 - 拆分执行和判断逻辑:先单独执行curl拿到退出码,再根据退出码分别提取URL写入对应日志,避免grep执行结果干扰请求成败判断
- 用
while read逐行读取curl命令,避免空白字符拆分命令的问题 - 修正URL提取正则,匹配curl命令末尾引号包裹的完整目标URL,兼容所有后缀的地址
修正后的可直接运行代码:
#!/bin/bash # 存储多条curl命令的变量,每条curl占一行 var='curl -X data -H "Referer:http://something.html" "http://example.com/url.zip" curl -X GET -H "Referer:http://test.com/page.html" "http://test.com/api/data" curl "http://wrong-domain-that-not-exist/404.zip"' # 初始化清空日志文件 > success.log > fail.log # 逐行读取curl命令,避免拆分错误 echo "$var" | while IFS= read -r f; do # 跳过空行 [ -z "$f" ] && continue # 执行curl请求:-f开启HTTP错误识别,-s静默输出,-o /dev/null丢弃响应内容 echo "$f" | bash -s -- -f -s -o /dev/null # 拿到curl执行的退出码 exit_code=$? # 提取当前命令的目标URL:匹配末尾引号包裹的http/https开头地址 target_url=$(echo "$f" | grep -oE '"https?://[^"]+"$' | tr -d '"') # 根据退出码写入对应日志 if [ $exit_code -eq 0 ]; then echo "$target_url" >> success.log else echo "$target_url" >> fail.log fi done
如果你的curl命令是存在独立文件(比如curl_list.txt,每行一条curl),只需要把循环部分改成从文件读取即可:
while IFS= read -r f; do [ -z "$f" ] && continue echo "$f" | bash -s -- -f -s -o /dev/null exit_code=$? target_url=$(echo "$f" | grep -oE '"https?://[^"]+"$' | tr -d '"') if [ $exit_code -eq 0 ]; then echo "$target_url" >> success.log else echo "$target_url" >> fail.log fi done < curl_list.txt
注意:Chrome复制的curl里Header参数值本身需要带引号,原示例里
-H Refferer:http://something.html缺少引号,遇到带特殊字符的地址会执行报错,使用前记得给Header值补上双引号。
内容的提问来源于stack exchange,提问作者Tathastu Pandya
相关产品推荐
相关产品推荐

