繁体   English   中英

如何在 terraform 中注入带有美元符号 ($) 的 bash 脚本?

[英]How to inject a bash script with a dollar sign ($) in terraform?

我有一个简单的 bash 脚本,它执行如下操作:

#!/bin/bash
a=$(curl -s http://metadata/endpoint/internal)
echo "$a - bar"

(这只是一个简化)。 请注意使用两个$符号来执行命令和解析变量。

使用 Terraform,我想在启动期间将此文件写入 GCP 实例。 根据 Terraform 的说明,我试图避免使用File Provisioner 使用google_compute_instance 2中的metadata_startup_script字段,我将脚本包括在内,以便我可以将它写入特定位置。

例如

  metadata_startup_script = <<-EOF
#!/bin/bash -xe
sudo tee /etc/myservice/serv.conf > /dev/null <<EOI
${file("${path.module}/scripts/simple_bash.sh")}
EOI
EOF

Terraform 在某处的下标中插入$ (在加载到 metadata_startup_script 中,或者在将脚本写入磁盘时。

因此,根据我用来尝试逃避插值的方法,它仍然无法写入。 比如我试过(下标):

echo "\$a - bar"
echo "${“$”}a - bar"
echo "$$a - bar"

根据 terraform 文档,我应该使用$$ ,但是当我在上面这样做时,我得到:

echo "1397a - bar"

所有这些都无法复制原始脚本。

我只是在寻找要写入磁盘的确切 bash 脚本。

我的目标是在没有额外转义序列的情况下执行上述操作(详见此处 - Terraform 中的 Escaping 美元符号),以便我可以继续运行原始脚本(用于调试目的)。

我也不想构建包含原始脚本的打包程序映像。

谢谢!

我不认为这是Terraform在这里吃你的变量插值,因为 Terraform 只理解${ (美元符号后跟大括号)作为开始插值,而你的例子只包含$a

但是,您似乎确实将一个 bash 脚本嵌入到另一个脚本中,因此在我看来,外部 bash 在内部 bash 有机会查看它之前解析您的$a似乎是合理的。 如果是这样,您可以使用 bash heredoc 语法的文字变体,如How to cat <> a file containing code?的答案中所述。 , 这样外层的 bash 就会把内容当作字面量,交给内层的 bash 去求值。

  metadata_startup_script = <<-EOF
#!/bin/bash -xe
sudo tee /etc/myservice/serv.conf > /dev/null <<'EOI'
${file("${path.module}/scripts/simple_bash.sh")}
EOI
EOF

请注意,我写了<<'EOI'而不是<<EOI ,这是根据其他问题的指导结合“此处文档”(粗体强调我的)的主要 Bash 文档

这种类型的重定向指示 shell 从当前源读取输入,直到看到仅包含单词(没有尾随空格)的行。 然后,所有读取到该点的行都将用作命令的标准输入(或文件描述符n ,如果指定了n )。

这里文档的格式是:

 [n]<<[-]word here-document delimiter

不对word执行参数和变量扩展、命令替换、算术扩展或文件名扩展。 如果word的任何部分被引用,则分隔符是对word删除引号的结果,并且不会扩展 here-document 中的行。 如果word未被引用,则 here-document 的所有行都经过参数扩展、命令替换和算术扩展,字符序列\newline将被忽略,并且必须使用\来引用字符\$`

如果重定向运算符是<<- ,那么所有前导制表符都将从输入行和包含定界符的行中删除。 这允许 shell 脚本中的 here-documents 以自然的方式缩进。


如果您的机器映像配置为在启动时运行cloud-init——通常但并非总是负责执行metadata_startup_script您可以通过使用Cloud Config YAML来实现类似的效果,而无需那么多 Bash 脚本间接寻址shell 脚本直接。

例如,如果您的意图只是将该文件的内容写入文件系统中的指定位置,您可能会遵循Writing out arbitrary files示例

  metadata_startup_script = <<-EOF
    #cloud-config
    ${yamlencode({
      write_files = [
        {
          encoding    = "b64"
          content     = filebase64("${path.module}/scripts/simple_bash.sh")
          path        = "/etc/myservice/serv.conf"
          owner       = "root:root"
          permissions = "0644"
        },
      ]
    }}
  EOF

Cloud-init 在启动生命周期的不同时间点评估 其模块 此处使用Write Files模块被指定为在实例首次启动时运行一次,这也符合 Cloud-init 通常处理裸 shell 脚本的方式。

我认为您的问题与 TF 插值无关。 我认为您因为正常的bash插值而遇到问题,因为它的bash将在编写其内容时尝试解析/etc/myservice/serv.conf中的$

常规解决方案是使用'EOI' ,而不是EOI

  metadata_startup_script = <<-EOF
#!/bin/bash -xe
sudo tee /etc/myservice/serv.conf > /dev/null <<'EOI'
${file("${path.module}/scripts/simple_bash.sh")}
EOI
EOF

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM