GitHub Actions中Terraform输出文件冗余行问题的原因及解决方法
GitHub Action中Terraform输出JSON包含冗余内容的原因及解决方法
问题场景
我在GitHub Action工作流中编写了以下代码:
- name: Save Terraform Output to JSON File run: | terraform output -json > output.json - name: Upload Terraform Output JSON File as Artifact uses: actions/upload-artifact@v3 with: name: terraformOutput path: output.json
但下载产物文件后,发现其中包含大量冗余行:
[command]/home/runner/work/_temp/59756a93-8dd6-479b-ac36-25cce5af6f4d/terraform-bin output -json { "hello": { "sensitive": false, "type": "string", "value": "world" } } ::debug::Terraform exited with code 0. ::debug::stdout: {%0A "hello": {%0A "sensitive": false,%0A "type": "string",%0A "value": "world"%0A }%0A}%0A ::set-output name=stderr:: ::set-output name=exitcode::0
期望产物文件仅包含以下内容:
{ "hello": { "sensitive": false, "type": "string", "value": "world" } }
原因分析
这些冗余内容来自GitHub Actions的命令包装器:
- GitHub Actions会自动包装
run步骤中的命令,打印执行的命令路径(以[command]/xxx开头的行) - 同时,Terraform的Action包装器会输出调试日志(以
::debug::开头的行)和工作流输出变量(::set-output::行),这些内容会被错误地重定向到output.json中——因为默认情况下run步骤会合并标准输出(stdout)和标准错误(stderr)的内容。
解决方法
要只保留Terraform的纯JSON输出,需要明确捕获Terraform命令的标准输出,排除包装器产生的额外内容,以下是几种可靠方案:
方案1:直接调用原始Terraform二进制文件
GitHub Actions中,Terraform的二进制文件路径可通过TERRAFORM_CLI_PATH环境变量获取,直接调用它能避免命令包装器的额外输出:
- name: Save Terraform Output to JSON File run: | "$TERRAFORM_CLI_PATH" output -json > output.json - name: Upload Terraform Output JSON File as Artifact uses: actions/upload-artifact@v3 with: name: terraformOutput path: output.json
方案2:用jq过滤有效JSON内容
如果无法直接调用原始二进制文件,可通过jq工具提取有效的JSON内容(前提是工作流环境已安装jq):
- name: Save Terraform Output to JSON File run: | terraform output -json | jq . > output.json - name: Upload Terraform Output JSON File as Artifact uses: actions/upload-artifact@v3 with: name: terraformOutput path: output.json
jq .会自动过滤非JSON内容,仅保留格式化后的有效JSON对象。
方案3:区分stdout和stderr重定向(不推荐生产环境)
若包装器的额外内容通过stderr输出,可只重定向stdout并丢弃stderr,但这种方式会丢失Terraform的真实错误信息:
- name: Save Terraform Output to JSON File run: | terraform output -json 1> output.json 2>/dev/null - name: Upload Terraform Output JSON File as Artifact uses: actions/upload-artifact@v3 with: name: terraformOutput path: output.json
内容的提问来源于stack exchange,提问作者Charlie Fish
相关产品推荐
相关产品推荐

