Makefile执行apply目标时读取terraform输出的变量echo为空如何解决
Makefile执行terraform后变量为空问题解决方案
根因
- Make默认会为目标下的每一行命令启动独立的子shell执行,前一行子shell内赋值的变量无法传递到后一行的子shell中,所以echo行读取不到前面的变量值。
- 你当前使用的
$(shell)是Make层面的内置函数,执行时机早于目标下所有命令的执行,会在terraform apply运行前就执行读取terraform输出的操作,若你是首次运行无历史状态文件,这一步直接会拿到空值,你当前能看到赋值日志只是因为本地已有之前生成的terraform状态缓存。
解决方案
两种方案可选:
方案1:命令连行执行(兼容性最好)
将变量赋值和后续所有需要用到变量的操作通过反斜杠连为同一行,让所有操作在同一个子shell内完成。同时将Make层面的$(shell)替换为shell层面的命令替换(用$$(...)转义,避免被Make提前解析),配合jq的-r参数去掉输出的引号:
apply: init @terraform apply -auto-approve @BUCKET=$$(terraform output -json | jq -r '.S3_Bucket.value') \ && DYNAMODB=$$(terraform output -json | jq -r '.dynamo_db_lock.value') \ && echo $$BUCKET \ # 后续sed命令可直接在同一链路上调用 && sed -i "s/你的占位符/$$BUCKET/g" 目标文件路径
提示:Makefile中目标下的所有命令行必须用Tab缩进,不能用空格,否则会触发语法错误
方案2:启用ONESHELL(写法更简洁)
如果你使用的是GNU Make 3.82及以上版本,可以在Makefile开头声明.ONESHELL特殊目标,该目标下的所有命令会在同一个shell内执行,支持直接跨行调用变量:
# 放在Makefile最顶部 .ONESHELL: apply: init @terraform apply -auto-approve BUCKET=$$(terraform output -json | jq -r '.S3_Bucket.value') DYNAMODB=$$(terraform output -json | jq -r '.dynamo_db_lock.value') @echo $$BUCKET # 后续sed命令直接调用即可 sed -i "s/你的占位符/$$BUCKET/g" 目标文件路径
内容的提问来源于stack exchange,提问作者David Villasmil
相关产品推荐
相关产品推荐

