Bash脚本循环执行curl请求仅获取最后一次响应的问题
问题
尝试遍历数组中的每个元素执行curl请求,所有URL单独请求均可正常工作,但脚本仅能获取到最后一个请求的响应。
脚本代码
tmp="{ \"data\":{ \"id\":\"sv-Ps7epZJypQGB4Jb3\", \"type\":\"state-versions\", \"relationships\":{ \"outputs\":{ \"data\":[ { \"id\":\"wsout-YDDEzn2h9Y9fJERB\", \"type\":\"state-version-outputs\" }, { \"id\":\"wsout-CYzpWK2uMDGFn9Yr\", \"type\":\"state-version-outputs\" }, { \"id\":\"wsout-RroeVzLsv6PxJ56A\", \"type\":\"state-version-outputs\" }, { \"id\":\"wsout-8ts3sHe7NsE46mN6\", \"type\":\"state-version-outputs\" } ] } } } }" echo "$tmp" output_ids=$(echo "${tmp}" | jq -r '.data.relationships.outputs.data[].id') echo "iic" base_url="https://app.terraform.io/api/v2/state-version-outputs/" declare -a tableau # Créez un fichier temporaire contenant le texte tempfile=$(mktemp) echo "$output_ids" > "$tempfile" # Parcourez chaque ligne du fichier et ajoutez-la au tableau while IFS= read -r ligne; do tableau+=("$ligne") done < "$tempfile" # Supprimez le fichier temporaire cat "$tempfile" rm "$tempfile" declare -p tableau # Accédez aux éléments du tableau for element in "${tableau[@]}"; do echo "Élément du tableau : $element" full_url="$base_url$element" echo "URL : $full_url" output_details=$(curl \ --header "Authorization: Bearer $TOKEN" \ --header "Content-Type: application/vnd.api+json" \ -s "$full_url") echo "$output_details" done
执行结果
{ "data":{ "id":"sv-Ps7epZJypQGB4Jb3", "type":"state-versions", "relationships":{ "outputs":{ "data":[ { "id":"wsout-YDDEzn2h9Y9fJERB", "type":"state-version-outputs" }, { "id":"wsout-CYzpWK2uMDGFn9Yr", "type":"state-version-outputs" }, { "id":"wsout-RroeVzLsv6PxJ56A", "type":"state-version-outputs" }, { "id":"wsout-8ts3sHe7NsE46mN6", "type":"state-version-outputs" } ] } } } } wsout-YDDEzn2h9Y9fJERB wsout-CYzpWK2uMDGFn9Yr wsout-RroeVzLsv6PxJ56A wsout-8ts3sHe7NsE46mN6 declare -a tableau=([0]=$'wsout-YDDEzn2h9Y9fJERB\r' [1]=$'wsout-CYzpWK2uMDGFn9Yr\r' [2]=$'wsout-RroeVzLsv6PxJ56A\r' [3]="wsout-8ts3sHe7NsE46mN6") Élément du tableau : wsout-YDDEzn2h9Y9fJERB URL : https://app.terraform.io/api/v2/state-version-outputs/wsout-YDDEzn2h9Y9fJERB Élément du tableau : wsout-CYzpWK2uMDGFn9Yr URL : https://app.terraform.io/api/v2/state-version-outputs/wsout-CYzpWK2uMDGFn9Yr Élément du tableau : wsout-RroeVzLsv6PxJ56A URL : https://app.terraform.io/api/v2/state-version-outputs/wsout-RroeVzLsv6PxJ56A Élément du tableau : wsout-8ts3sHe7NsE46mN6 URL : https://app.terraform.io/api/v2/state-version-outputs/wsout-8ts3sHe7NsE46mN6 {"data":{"id":"wsout-8ts3sHe7NsE46mN6","type":"state-version-outputs","attributes":{"name":"db_username","sensitive":false,"type":"string","value":"diagngrowdbuser","detailed-type":"string"},"links":{"self":"/api/v2/state-version-outputs/wsout-8ts3sHe7NsE46mN6"}}}
解决方案
从执行结果里的declare -p tableau输出可以看到,前三个ID元素末尾带有不可见的回车符\r,这会导致拼接后的URL包含无效字符,服务器无法识别正确的ID,因此请求失败;只有最后一个没有\r的ID请求成功。
修复方法1:移除回车符
在提取ID时,直接用tr -d '\r'去掉所有回车符,修改提取ID的代码:
output_ids=$(echo "${tmp}" | jq -r '.data.relationships.outputs.data[].id' | tr -d '\r')
修复方法2:简化脚本(推荐)
不需要临时文件和数组,直接遍历jq的输出,同时处理回车符:
tmp="{ \"data\":{ \"id\":\"sv-Ps7epZJypQGB4Jb3\", \"type\":\"state-versions\", \"relationships\":{ \"outputs\":{ \"data\":[ { \"id\":\"wsout-YDDEzn2h9Y9fJERB\", \"type\":\"state-version-outputs\" }, { \"id\":\"wsout-CYzpWK2uMDGFn9Yr\", \"type\":\"state-version-outputs\" }, { \"id\":\"wsout-RroeVzLsv6PxJ56A\", \"type\":\"state-version-outputs\" }, { \"id\":\"wsout-8ts3sHe7NsE46mN6\", \"type\":\"state-version-outputs\" } ] } } } }" echo "$tmp" echo "iic" base_url="https://app.terraform.io/api/v2/state-version-outputs/" # 直接遍历jq输出,同时移除回车符 echo "${tmp}" | jq -r '.data.relationships.outputs.data[].id' | tr -d '\r' | while IFS= read -r element; do echo "Élément du tableau : $element" full_url="$base_url$element" echo "URL : $full_url" output_details=$(curl \ --header "Authorization: Bearer $TOKEN" \ --header "Content-Type: application/vnd.api+json" \ -s "$full_url") echo "$output_details" done
补充说明
curl的-s参数会静默执行,不输出错误信息,所以前三个请求失败时没有任何提示,看起来像是没有响应。如果需要排查问题,可以去掉-s参数,或者加上-v查看详细请求过程。
内容的提问来源于stack exchange,提问作者Pierre
相关产品推荐
相关产品推荐

