Bash脚本处理Git提交JSON文件时重复调用API问题求助
问题:Git提交的JSON文件被重复执行API调用
提交file1.json至file5.json共5个文件时,每个文件被重复执行5次,期望每个文件仅执行一次。尝试用数组记录已处理文件但未生效。
问题原因
- 数组匹配逻辑缺陷:原脚本用
[[ ! " ${processed_files[@]} " =~ " ${file} " ]]判断文件是否已处理,当文件名包含特殊字符(如空格、*)或匹配边界模糊时,会导致判断失效,重复处理同一文件。 - 文件名遍历方式错误:直接用
for file in $files遍历git diff输出,若文件名包含空格会被分割成多个元素,引发异常处理。 - CURL命令语法错误:原脚本中
-F "$endpoint/deploy"将API URL错误当作表单字段,导致请求无效,可能触发重复执行逻辑。
解决方案
- 使用关联数组记录已处理文件,判断逻辑更可靠,不受文件名特殊字符影响。
- 用
while read循环读取git diff输出,正确处理带空格的文件名。 - 修正CURL命令的语法,将API URL放在命令末尾,而非作为
-F参数。 - 优化状态提取逻辑,避免依赖字符串切割的脆弱写法(可选,用jq工具更可靠)。
修正后的完整脚本
#!/bin/bash # 用关联数组记录已处理文件,判断更可靠 declare -A processed_files # Login配置 endpoint="xxx" username="xxx" password="xxx" auth_token="xxx" # 替换为实际的授权令牌 # 获取提交中的文件列表,用while read正确处理带空格的文件名 git diff --name-only HEAD HEAD~1 | while read -r file; do # 仅处理JSON文件 if [[ "$file" == *.json ]]; then # 判断文件是否已处理 if [[ -z "${processed_files[$file]}" ]]; then # 标记为已处理 processed_files["$file"]=1 echo "开始执行任务:$file" # 部署操作:修正curl语法,URL放在末尾 curl -k -s -H "Authorization: $auth_token" -X POST -F "definitionsFile=@../$file" "$endpoint/deploy" # 运行任务并获取runId submit=$(curl -k -s -H "Authorization: $auth_token" -X POST -F "jobDefinitionsFile=@../$file" "$endpoint/run") # 推荐用jq提取runId(若环境安装了jq):runid=$(echo "$submit" | jq -r '.runId') runid=$(echo "${submit##*runId\" : \"}" | cut -d '"' -f 1) # 等待任务结束 echo "等待任务结束:$runId" while true; do sleep 10 tmp=$(curl -k -s -H "Authorization: $auth_token" "$endpoint/run/status/$runid") # 检查任务是否失败 if echo "$tmp" | grep -q 'Not OK'; then echo "任务失败:$file" curl -k -s -H "Authorization: $auth_token" -X POST "$endpoint/session/logout" exit 2 fi # 提取任务状态 # 推荐用jq:status=$(echo "$tmp" | jq -r '.status') tmp2=$(echo "${tmp##*\"type\" : \"Folder\",\n}") status=$(echo "${tmp2##*\"status\" : \"}" | cut -d '"' -f 1) # 判断任务是否结束 if [[ "$status" == Ended* ]]; then echo "任务完成:$file" break fi done else echo "任务已执行,跳过:$file" fi fi done # 登出 curl -k -s -H "Authorization: $auth_token" -X POST "$endpoint/session/logout" # 最终状态判断 if [[ "$status" == *Not* ]]; then echo '任务执行失败!' exit 1 else echo '所有任务执行成功!' exit 0 fi
额外优化建议
- 若环境允许,安装
jq工具(sudo apt install jq或brew install jq),用jq提取JSON字段,替代脆弱的字符串切割,例如:runid=$(echo "$submit" | jq -r '.runId') status=$(echo "$tmp" | jq -r '.status') - 增加错误处理,比如检查curl命令是否执行成功,避免因网络问题导致后续逻辑出错。
- 将敏感信息(如授权令牌)放在环境变量中,而非硬编码在脚本里。
内容的提问来源于stack exchange,提问作者sharete
相关产品推荐
相关产品推荐

