使用curl上传至对象存储时如何处理错误并实现重试?
检测上传错误与重试方案
一、错误检测方式
1. 利用curl退出码
curl执行失败(如网络断开、连接超时)会返回非0退出码,可通过$?变量直接获取执行状态。
2. 捕获HTTP响应状态码
通过curl的-w "%{http_code}"参数,在命令执行后输出HTTP状态码,以此判断业务层面的错误:
- 2xx(如200、201):上传成功
- 429:速率限制(需重试)
- 5xx(如500、503):服务器端错误(适合重试)
- 其他4xx(如403、404):通常是配置/权限问题,无需重试
二、带重试逻辑的bash脚本实现
下面是完整的脚本示例,包含重试次数控制、动态等待(支持解析Retry-After头)、错误判断:
#!/bin/bash # 配置参数 UPLOAD_URL="https://mybucket.fsn1.your-objectstorage.com//myfile.bin" LOCAL_FILE="myfile.bin" S3_KEY="${S3KEY}" MAX_RETRIES=5 INITIAL_WAIT=2 # 初始重试间隔(秒) # 重试循环 for ((retry=0; retry<=MAX_RETRIES; retry++)); do # 执行curl上传,捕获HTTP状态码和Retry-After头 RESPONSE=$(curl -sS -w "\nHTTP_CODE:%{http_code}\nRETRY_AFTER:%{response_header_Retry-After}" \ -T "$LOCAL_FILE" \ --user "$S3_KEY" \ --aws-sigv4 "aws:amz:fsn1:s3" \ "$UPLOAD_URL") # 提取状态码和Retry-After值 HTTP_CODE=$(echo "$RESPONSE" | grep -oP 'HTTP_CODE:\K\d+') RETRY_AFTER=$(echo "$RESPONSE" | grep -oP 'RETRY_AFTER:\K\d+') # 检查上传是否成功 if [ "$HTTP_CODE" -ge 200 ] && [ "$HTTP_CODE" -lt 300 ]; then echo "上传成功" exit 0 fi # 达到最大重试次数则退出 if [ "$retry" -eq "$MAX_RETRIES" ]; then echo "已达最大重试次数,上传失败,最终状态码:$HTTP_CODE" exit 1 fi # 确定等待时间:优先遵循服务器返回的Retry-After,否则用指数退避 if [ -n "$RETRY_AFTER" ]; then WAIT_TIME="$RETRY_AFTER" echo "触发速率限制,服务器要求等待$WAIT_TIME秒后重试" else WAIT_TIME=$((INITIAL_WAIT * (2 ** retry))) # 指数退避:间隔逐次翻倍 echo "上传失败(状态码:$HTTP_CODE),$WAIT_TIME秒后进行第$((retry+1))次重试" fi sleep "$WAIT_TIME" done
三、关键细节说明
- 指数退避策略:每次重试间隔翻倍,避免持续触发速率限制,比固定间隔更合理
- Retry-After解析:如果对象存储返回该响应头,会自动遵循服务器指定的等待时间
- curl参数:
-sS:静默模式但保留错误输出,避免冗余信息干扰状态码捕获-w:自定义输出格式,方便提取状态码和响应头- 原命令URL中的双斜杠
//若为笔误可修正为单斜杠,不影响功能的话可保留
内容的提问来源于stack exchange,提问作者Jarle Hammen Knudsen
相关产品推荐
相关产品推荐

