如何用PowerShell脚本运行Terraform CLI并传递map类型变量?
问题场景
我的Terraform文件infrastructure.tf中变量声明如下:
variable "tags" { type = map(string) }
我用PowerShell脚本执行terraform plan命令,代码如下:
$command = "plan" $options = @( "'--var=tags={a:\`"b\`"}'" "--out=path/to/out.tfplan" ) Write-Host terraform,$command,$options & terraform $command $options
Write-Host输出的命令内容为:
terraform plan '--var=tags={a:\"b\"}' --out=path/to/out.tfplan
把这个命令直接复制到PowerShell 7.2(pwsh)交互会话里能正常运行,但用脚本里的& terraform执行时就报错:
Error: Too many command line arguments
To specify a working directory for the plan, use the global -chdir flag.
Terraform文档提到Windows上用PowerShell运行可能存在引号解析问题,但未明确是否包含PowerShell 7.2。在macOS的pwsh交互会话里能正常传递带引号的参数,但脚本执行时同样失败。我们的DevOps工具链完全基于PowerShell,希望找到可行的解决方法,若无法解决再考虑替代方案。
已尝试的方法:
- 对
$options使用展开语法(如@options) - 在
$options开头添加停止解析标记(--%) - 尝试多种单/双引号组合
- 移除
\符号,但此操作会导致交互式命令也无法运行
可行解决方案
方法1:修正参数格式,避免多余嵌套引号
PowerShell调用外部命令时,参数不需要额外添加外层引号,直接传递解析后的参数内容即可。修改$options的定义:
$command = "plan" $options = @( "--var=tags={a:`"b`"}" "--out=path/to/out.tfplan" ) & terraform $command $options
这里用PowerShell的原生转义符`来保留参数内的双引号,无需在外层用单引号包裹整个--var参数,PowerShell会自动将该参数作为单个整体传递给Terraform。
方法2:使用Terraform变量文件替代命令行传参
如果命令行参数的引号处理始终存在问题,推荐使用Terraform官方推荐的变量文件(如terraform.tfvars)传递复杂变量:
创建terraform.tfvars文件:
tags = { a = "b" }
然后在PowerShell脚本中直接执行:
& terraform plan --out=path/to/out.tfplan
Terraform会自动加载同目录下的terraform.tfvars文件,彻底避免命令行的引号解析问题。
方法3:用Start-Process精确控制参数传递
如果仍需要通过命令行传参,可以使用Start-Process来更精准地控制参数边界:
$arguments = @( "plan", "--var=tags={a:`"b`"}", "--out=path/to/out.tfplan" ) Start-Process -FilePath terraform -ArgumentList $arguments -Wait -NoNewWindow
Start-Process的-ArgumentList参数会正确处理参数的边界,规避PowerShell的自动解析问题。
内容的提问来源于stack exchange,提问作者Michiel van Oosterhout

