gpt4 book ai didi

powershell - powershell 中的 Terraform state mv 命令使用带空格的名称失败

转载 作者:行者123 更新时间:2023-12-02 23:33:07 25 4
gpt4 key购买 nike

我们有一个问题,当我们尝试使用 tf state mv 移动项目时,它会在 powershell 中错误地解析。

正如你在下面看到的,terraform CLI 将空间作为一个新项目插入,并且状态 mv 调用失败

如果我们在命令提示符下运行该命令并修改转义,它将起作用,我们希望找到一种方法使其在 powershell 中工作,可能具有自定义转义。

PS 中的重现步骤 :

Terraform init
Terraform plan
Terraform apply
Terraform state mv 'local_file.file[\"b c\"]' 'local_file.file[\"e f\"]'

PS中的命令(失败) terraform state mv 'local_file.file[\"b c\"]' 'local_file.file[\"e f\"]'
CMD中的命令 terraform state mv "local_file.file[\"b c\"]" "local_file.file[\"e f\"]"
输出

2020/06/14 23:59:22 [信息] Terraform 版本:0.12.23
2020/06/14 23:59:22 [INFO] Go 运行时版本:go1.12.13
2020/06/14 23:59:22 [INFO] CLI 参数:字符串{“C:\Windows\terraform.exe”、“state”、“mv”、“local_file.file[“b”、“c”] ”, “local_file.file[“e”, “f”]”}
2020/06/14 23:59:22 [DEBUG] 尝试打开 CLI 配置文件:C:\Users\p120b60.CORPADDS\AppData\Roaming\terraform.rc
2020/06/14 23:59:22 [DEBUG] 文件不存在,但不需要。无视。
2020/06/14 23:59:22 [INFO] CLI 命令参数:字符串{“state”、“mv”、“local_file.file[“b”、“c”]”、“local_file.file[“e” , “F”]”}
正好有两个参数预期。

主文件
provider “azurerm” {

version = “=2.13.0”

skip_provider_registration = “true”

features {}

}

locals {

filenames = toset([“a”, “b c”])

}

terraform {

backend “local” {

path = "./terraformconfig.tfstate"
}

}

resource “local_file” “file” {

for_each = local.filenames

filename = each.value

}

TF版
Terraform v0.12.23

provider.azurerm v2.13.0
provider.local v1.4.0

最佳答案

当您使用 PowerShell(包括 Terraform)运行非 PowerShell 程序时,您需要同时处理 PowerShell 对命令行的解析和最终程序对命令行的解析。

Windows 上的 Terraform 期望在 the Microsoft C++ command line processing patterns 之后接收命令行字符串, 意思是:

  • 参数由空格分隔,空格或制表符。
  • 由双引号 ("string") 包围的字符串被解释为单个参数,而不管其中包含的空格。带引号的字符串可以嵌入到参数中。
  • 以反斜杠 (\") 开头的双引号被解释为文字双引号字符 (")。
  • 反斜杠按字面解释,除非它们紧跟在双引号之前。
  • 如果偶数个反斜杠后跟一个双引号,则每对反斜杠都会在 argv 数组中放置一个反斜杠,并将双引号解释为字符串分隔符。
  • 如果奇数个反斜杠后跟双引号,则每对反斜杠都会在argv数组中放置一个反斜杠,双引号被剩余的反斜杠“转义”,导致字面双引号(“) 放置在 argv.

  • 如您所见,Terraform 在其早期日志中写出上述处理规则的结果,这些规则发生在 Terraform 自己的代码开始运行之前。

    您的情况面临的挑战是,上述规则是在通过正常的 Windows 机制(例如 the CreateProcess function)运行程序的假设下编写的。 ,其中所有参数都作为 lpCommandLine 中的单个字符串传递争论。但这不是 PowerShell 的工作方式......

    PowerShell 本身就是一种脚本语言,因此拥有自己的解析器,用于解释命令行。当使用 PowerShell 自己的 cmdlet 时,这是完全合理且合理的,因为 cmdlet 期望将它们的参数作为由该解析产生的不同 PowerShell 值接收。

    当您使用 PowerShell 运行不是 PowerShell cmdlet 的程序时会出现问题:PowerShell 将使用自己的规则解析命令行,然后检测命令行正在运行非 PowerShell 程序,因此必须尝试使用它已经解析的单独值重建单个命令行字符串。

    这意味着当我们使用 PowerShell 运行普通程序时,我们本质上需要欺骗 PowerShell 构造一个符合上述 Microsoft C++ 命令行处理模式的字符串,因为 PowerShell 本身就是构造最终字符串的一个。

    避免这些问题的一个非常重要的方法是通过使用 Start-Process 手动启动程序来完全阻止 PowerShell 解释参数本身。 cmdlet,它采用 lpCommandLine值作为单个字符串参数:
    & Start-Process -FilePath "terraform" -ArgumentList "import `"\`"null_resource.things[\\\`"thing one\\\`"]\`"`" 800778739314064726"

    PowerShell 使用反引号作为它的转义字符,所以上面是使用反引号来转义引号以强制 PowerShell 按字面意思接受它们,然后使用反斜杠以便一旦 PowerShell 完成解析结果是一个字符串,正常的命令行处理规则应该能够解释。

    如果您愿意详细研究 PowerShell 解析规则和外部程序启动行为并弄清楚如何让 PowerShell 自己构建合适的字符串,那么获得相同结果的方法就不那么极端了,但通常更容易使用普通的 Windows 命令解释器——旨在与普通 Windows 程序期望命令行参数的方式兼容——并将 PowerShell 保存在您主要使用 PowerShell cmdlet 的情况下,因此 PowerShell 的更高级的命令行解析是有帮助的,而不是一个障碍。

    关于powershell - powershell 中的 Terraform state mv 命令使用带空格的名称失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62391243/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com