Bash脚本中Curl调用API失败的问题排查与修复指导
修正Bash脚本中curl请求JSON无效的问题
问题场景
有一个在Linux上运行的Bash脚本,通过curl调用API接口,接收用户输入后执行始终返回{"message": "Invalid request body"}错误,但手动执行脚本输出的curl命令却能成功调用API。
原脚本内容:
#!/bin/bash # Constants api_key="Thdshd760Jd" api_url="https://execute-api.amazonaws.com/prod/v1/archive;done" # User input read -p "Enter projectName: " projectName read -p "Enter siteName: " siteName read -p "Enter emailAddress: " emailAddress read -p "Enter the path to the file containing disk names: " disk_file # Read disk names from the file and create a comma-separated string disks=$(awk '{printf "\"%s\", ", $1}' "$disk_file" | sed 's/, $//') # Create JSON payload in Bash json_payload="'{\"projectName\": \"$projectName\", \"siteName\": \"$siteName\", \"disks\": [$disks], \"emailAddress\": \"$emailAddress\"}'" # Make the API request using curl curl -vv -X POST -H "x-api-key: $api_key" -H "Content-Type: application/json" -d "$json_payload" $api_url echo 'curl -vv -X POST -H "x-api-key: '$api_key'" -H "Content-Type: application/json" -d '$json_payload' '$api_url''
执行过程:
$ ./curl_api_call.sh Enter projectName: my_disk001 Enter siteName: JLDC Enter emailAddress: labtest@example.com Enter the path to the file containing disk names: demo_file Note: Unnecessary use of -X or --request, POST is already inferred. {"message": "Invalid request body"} curl -vvvvvv -X POST -H "x-api-key: Thdshd760Jd" -H "Content-Type: application/json" -d '{"projectName": "my_disk001", "siteName": "JLDC", "disks": ["my_disk001"], "emailAddress": "labtest@example.com"}' https://execute-api.amazonaws.com/prod/v1/archive
另外尝试的循环版本也报相同错误:
for i in `cat` ; do curl -vvvvvv -X POST -H "x-api-key: Thdshd760Jd" -H "Content-Type: application/json" -d '{"projectName": "$i", "siteName": "JLDC", "disks": ["$i"], "emailAddress": "labtest@example.com"}' https://execute-api.amazonaws.com/prod/v1/archive;done
错误原因
- JSON payload被多余单引号包裹:脚本中
json_payload="'{...}'"的写法,给整个JSON字符串套了一层单引号。curl发送的请求体实际是'{"projectName": ...}'(包含外层单引号),这不符合JSON格式规范,导致API解析失败。而手动执行时去掉了外层单引号,所以请求合法。 - 循环版本变量未展开:循环里用单引号包裹JSON内容,
$i不会被Bash解析为变量值,发送的是字面量"$i",API自然无法识别。
修正方案
1. 修正原脚本
- 移除
json_payload外层的单引号,直接用双引号包裹JSON(注意转义内部双引号);或者用printf构建JSON,避免转义错误。 - 给
api_url添加双引号,避免Bash解析;为命令分隔符。
修正后的完整脚本:
#!/bin/bash # Constants api_key="Thdshd760Jd" api_url="https://execute-api.amazonaws.com/prod/v1/archive;done" # User input read -p "Enter projectName: " projectName read -p "Enter siteName: " siteName read -p "Enter emailAddress: " emailAddress read -p "Enter the path to the file containing disk names: " disk_file # Read disk names from the file and create a comma-separated string disks=$(awk '{printf "\"%s\", ", $1}' "$disk_file" | sed 's/, $//') # 用printf构建JSON,避免转义混乱 json_payload=$(printf '{"projectName": "%s", "siteName": "%s", "disks": [%s], "emailAddress": "%s"}' "$projectName" "$siteName" "$disks" "$emailAddress") # 调用curl时给api_url加双引号,处理特殊字符 curl -vv -X POST -H "x-api-key: $api_key" -H "Content-Type: application/json" -d "$json_payload" "$api_url" # 输出调试命令时确保引号正确 echo "curl -vv -X POST -H \"x-api-key: $api_key\" -H \"Content-Type: application/json\" -d '$json_payload' \"$api_url\""
2. 修正循环版本
需要让$i变量正常展开,有两种写法:
- 方法1:用双引号包裹JSON,转义内部双引号
for i in $(cat); do curl -vvvvvv -X POST -H "x-api-key: Thdshd760Jd" -H "Content-Type: application/json" -d "{\"projectName\": \"$i\", \"siteName\": \"JLDC\", \"disks\": [\"$i\"], \"emailAddress\": \"labtest@example.com\"}" https://execute-api.amazonaws.com/prod/v1/archive done
- 方法2:用单引号拼接变量(更清晰,减少转义)
for i in $(cat); do curl -vvvvvv -X POST -H "x-api-key: Thdshd760Jd" -H "Content-Type: application/json" -d '{"projectName": "'"$i"'", "siteName": "JLDC", "disks": ["'"$i"'"], "emailAddress": "labtest@example.com"}' https://execute-api.amazonaws.com/prod/v1/archive done
内容的提问来源于stack exchange,提问作者user2023
相关产品推荐
相关产品推荐

