![](/img/trans.png)
[英]How to use value from bash script when creating resource via terraform
[英]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.