如何在Bash脚本中处理Curl请求失败并跳过故障服务器
处理Bash Curl请求中的故障服务器跳过问题
你的问题核心是只要有一台服务器返回无效JSON或无响应,整个输出的JSON文件就会损坏甚至为空——这是因为原脚本没有对curl请求结果做任何校验,直接用jq解析失败响应会触发错误,甚至中断后续输出;同时原有的逗号处理逻辑也会因为跳过服务器而破坏JSON格式。
下面是改进后的脚本,附带详细的优化说明:
改进后的完整脚本
#!/bin/bash CONFIG=config.json jsondata=data.json # 初始化JSON文件的头部结构 echo '{ "success": "OK", "servers": {' > "$jsondata" # 标记是否是第一个要写入的服务器条目,解决逗号位置问题 first_entry=true # 遍历配置文件中的所有服务器键名 jq -r '.servers|keys[]' "$CONFIG" | while read key ; do # 从配置文件中提取当前服务器的IP和端口(请根据你的config.json实际结构调整) # 假设config.json结构示例:{"servers": {"server1": {"ip": "192.168.1.10", "port": "8080"}, ...}} IP=$(jq -r ".servers[\"$key\"].ip" "$CONFIG") PORT=$(jq -r ".servers[\"$key\"].port" "$CONFIG") HTTP="http" # 如果需要支持HTTPS,可以改成"https"或从配置中读取 # 执行curl请求:-s静默模式,-f确保HTTP错误时返回非0,-w捕获HTTP状态码 RESPONSE=$(curl -s -f -w "%{http_code}" "$HTTP://$IP:$PORT/api") # 分离HTTP状态码和响应体(状态码是最后3位) HTTP_STATUS=${RESPONSE: -3} RESPONSE_BODY=${RESPONSE%???} # 双重校验:HTTP状态码正常(200-299)且响应体是有效JSON if [ "$HTTP_STATUS" -ge 200 ] && [ "$HTTP_STATUS" -lt 300 ] && echo "$RESPONSE_BODY" | jq -e . >/dev/null 2>&1; then # 如果不是第一个条目,先写入逗号保证JSON格式合法 if [ "$first_entry" = false ]; then echo "," >> "$jsondata" fi first_entry=false # 解析需要的字段并写入JSON文件 DATA1=$(echo "$RESPONSE_BODY" | jq '.data1') DATA2=$(echo "$RESPONSE_BODY" | jq '.data2') echo " \"$key\": {" >> "$jsondata" echo " \"data1\": $DATA1," >> "$jsondata" echo " \"data2\": $DATA2" >> "$jsondata" echo " }" >> "$jsondata" # 输出成功日志到stderr,不影响JSON文件内容 echo "[INFO] Successfully fetched data from $key ($IP:$PORT)" >&2 else # 输出错误日志到stderr,方便排查问题 echo "[ERROR] Failed to get valid data from $key ($IP:$PORT). HTTP Status: $HTTP_STATUS, Response: $RESPONSE_BODY" >&2 fi done # 完成JSON文件的尾部结构 echo "} }" >> "$jsondata" echo "[INFO] Final JSON file generated at $jsondata" >&2
关键优化点说明
- curl请求的可靠性校验:
用-f参数让curl在HTTP状态码为4xx/5xx时直接返回非0错误码,同时通过-w "%{http_code}"捕获具体状态码,方便区分是网络不通还是服务器返回业务错误。 - JSON有效性验证:
使用jq -e .检查响应体是否为合法JSON,-e参数会让jq在解析失败时返回非0,结合>/dev/null 2>&1隐藏冗余输出,只关注校验结果。 - JSON格式的稳定性:
用first_entry变量替代原脚本的i计数来控制逗号输出,即使跳过多台故障服务器,也能保证生成的JSON始终是合法格式,不会出现多余或缺失的逗号。 - 错误日志分离:
所有日志信息(成功/失败)都输出到标准错误流(>&2),不会污染JSON文件内容,同时方便你运行脚本时查看哪些服务器出了问题。 - 配置读取优化:
补充了从config.json中提取IP和端口的逻辑,原脚本中这两个变量是硬编码的,现在更灵活适配你的配置文件(请根据实际的config.json结构调整jq提取语句)。
内容的提问来源于stack exchange,提问作者MAx Shvedov




