Terraform中如何在单个command块内处理执行多行命令
报错根因
HCL语法明确规定:双引号包裹的普通字符串不支持直接物理换行。你之前把带换行的命令直接塞在双引号里,哪怕加了\n转义但保留了实际换行,就会触发你看到的语法错误。
除此之外你之前的配置还有两个会导致后续执行失败的隐藏问题:
- 解压tar包后没有切换到生成的
kubernetes-harness-delegate目录(你之前笔误拼成了kubernetes-harness-delagate),后续生成的util.sh会落在错误路径 - 直接在command里写bash的
$变量,会被Terraform识别为自身的插值语法,触发变量未定义报错
实现方案
使用HCL原生的字面量heredoc语法编写单个command块即可,这种写法会把块内所有内容作为纯文本传递给bash,不会触发Terraform的插值解析,也不需要手动转义特殊字符,所有命令可以按bash原生语法顺序编写,不需要拆分多个provisioner配置。
完整可用配置如下:
resource "null_resource" "delegate" { triggers = { cluster_arn = module.primary.cluster_arn } provisioner "local-exec" { interpreter = ["/bin/bash", "-c"] command = <<-'EOT' set -euo pipefail # 解压Delegate安装包 tar -xvf harness-delegate-kubernetes.tar # 进入解压后生成的工作目录,注意核对实际目录名修正拼写 cd kubernetes-harness-delegate # 生成util.sh工具脚本 cat <<-EOF > util.sh SRC_FILE=harness-delegate.yaml TMP_FILE=harness-delegate.tmp DELEGATE_NAME=$1 if [ $# -lt 1 ]; then echo "usage utils.sh <name>" exit 0 fi DST_FILE=harness-${DELEGATE_NAME}.yaml if [ -f $DST_FILE ]; then echo "File $DST_FILE exists. Exiting..." exit 1 fi if [ ! -f ${TMP_FILE} ]; then echo "creating $TMP_FILE" cp $SRC_FILE $TMP_FILE dname=$(sed -n "1,/^.*harness.io.name/s?^.*harness.io/name: ??p" $TMP_FILE) sed -i -e "s/$dname/DELEGATENAME/" $TMP_FILE fi echo "creating $DST_FILE" cp $TMP_FILE $DST_FILE sed -i -e "s/DELEGATENAME/${DELEGATE_NAME}/" $DST_FILE EOF # 后续需要执行的其他步骤直接在下方追加即可 chmod +x util.sh EOT } }
配置说明
<<-'EOT'是HCL的缩进式heredoc标记,给标记加单引号后,Terraform不会解析块内的插值表达式,bash脚本里的$变量、子命令$()都可以直接写,不需要额外转义- 开头的
set -euo pipefail是bash标准容错配置,任意命令执行失败会直接终止流程,避免异常状态下执行后续步骤 - 块内所有命令按执行顺序从上到下编写即可,和本地写bash脚本逻辑完全一致,不需要加
\n转义,也不需要拆分多个command块 - 注意heredoc的结束标记
EOT必须顶格写,前面不能有空格或缩进,否则会触发语法错误
内容的提问来源于stack exchange,提问作者R. Barrett
相关产品推荐
相关产品推荐

