Terraform漂移检测脚本异常:grep过滤失效输出完整Plan内容
Terraform配置漂移检测脚本问题修复
问题说明
编写Shell脚本检测Terraform配置漂移时,将terraform plan的输出过滤后存入tf_plan变量,但脚本执行时会输出完整的Plan内容,而非预期的过滤结果。手动执行单条命令可得到正确输出,但脚本运行不符合预期。
用户脚本
i=environment terraform init tf_plan=$(terraform plan | grep -v "Refreshing state" | grep -v "data") drift_check=`echo $tf_plan | grep -c 'to add\|to change\|to destroy'` if [[ $drift_check -ge 1 ]] then echo "Drift detected in environment $i" printf "%s:%s" "$i" "`echo $tf_plan | grep -E 'to add|to change|to destroy'`" else echo "No drift detected in environment $i" printf "%s:%s" "$i" "`echo $tf_plan | grep -E 'No changes'`" fi
预期输出(存在漂移时)
environment:Plan: 0 to add, 1 to change, 0 to destroy.
手动执行结果
echo $tf_plan | grep -c 'to add\|to change\|to destroy' 1 echo $tf_plan | grep -E 'to add|to change|to destroy' Plan: 0 to add, 1 to change, 0 to destroy. printf "%s:%s" "$i":"`echo $tf_plan | grep -E 'to add|to change|to destroy'`" environment:Plan: 0 to add, 1 to change, 0 to destroy
脚本执行时tf_plan的实际内容
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: ~ update in-place Terraform will perform the following actions: # elasticstack_elasticsearch_index.idx1 will be updated in-place ~ resource "elasticstack_elasticsearch_index" "idx_salesorder_2019_v6" { id = "xyzadcfgd/idx1" ~ mappings = jsonencode( ~ { ~ properties = { ~ address = { ~ properties = { ~ addressdetails = { ~ properties = { - streetlocation = { - fields = { - keyword = { - ignore_above = 256 - type = "keyword" } } - type = "text" } # (30 unchanged attributes hidden) } } # (1 unchanged attribute hidden) } } # (3 unchanged attributes hidden) } } ) name = "idx1" # (8 unchanged attributes hidden) # (9 unchanged blocks hidden) } Plan: 0 to add, 1 to change, 0 to destroy.
问题原因
- 过滤规则无效:当前
grep -v "Refreshing state" | grep -v "data"仅排除包含指定字符串的行,但Terraform Plan的资源详情行不包含这些内容,因此全部保留在tf_plan变量中。 - 变量引用未加双引号:
echo $tf_plan会将变量中的换行符转换为空格,导致文本格式混乱,虽然手动执行时能侥幸匹配到目标行,但脚本中变量本身包含大量冗余内容,最终输出不符合预期。
修复方案
方案1:精准过滤Terraform Plan输出
直接提取关键行(Plan:或No changes开头的行),减少变量冗余:
i=environment terraform init # 仅保留包含Plan:或No changes的行 tf_plan=$(terraform plan | grep -E 'Plan:|No changes') drift_check=$(echo "$tf_plan" | grep -c 'to add\|to change\|to destroy') if [[ $drift_check -ge 1 ]] then echo "Drift detected in environment $i" printf "%s:%s\n" "$i" "$(echo "$tf_plan" | grep -E 'to add|to change|to destroy')" else echo "No drift detected in environment $i" printf "%s:%s\n" "$i" "$(echo "$tf_plan" | grep -E 'No changes')" fi
方案2:优化变量引用与过滤逻辑
如需保留更多上下文,确保变量引用时加双引号,避免格式丢失:
i=environment terraform init tf_plan=$(terraform plan | grep -v "Refreshing state" | grep -v "data") # 使用here string传递变量,避免echo的格式转换问题 drift_check=$(grep -c 'to add\|to change\|to destroy' <<< "$tf_plan") if [[ $drift_check -ge 1 ]] then echo "Drift detected in environment $i" printf "%s:%s\n" "$i" "$(grep -E 'to add|to change|to destroy' <<< "$tf_plan")" else echo "No drift detected in environment $i" printf "%s:%s\n" "$i" "$(grep -E 'No changes' <<< "$tf_plan")" fi
关键优化点
- 变量引用时始终加双引号(
"$tf_plan"),保留原始换行和格式。 - 使用
<<<here string替代echo $tf_plan | grep,减少子进程开销,避免格式转换问题。 - 精准过滤Terraform输出,只保留需要的关键行,避免变量存储冗余内容。
内容的提问来源于stack exchange,提问作者Bhanu Pratap
相关产品推荐
相关产品推荐

