OpenTofu变量可用于inline命令,远程执行脚本为何无法读取?
问题原因
OpenTofu对inline命令里的${var.xxx}变量是本地预解析:在发送命令到远程机器前,OpenTofu会先把变量替换成实际值,再将完整的命令字符串传给远程执行,所以远程bash拿到的是已经替换好的内容。
而file provisioner是直接把本地的base.sh文件原封不动传输到远程机器,脚本里的${var.new_root_passwd}这类写法,到了远程bash环境中会被当作bash自身的变量引用,但远程机器根本没定义这些变量,自然会触发「bad substitution」错误。
解决方案
针对这个问题,有三种常用的解决思路:
1. 使用模板生成带变量的脚本
把base.sh改成模板文件,用OpenTofu的templatefile函数在本地替换变量后,再传输到远程:
- 先创建模板文件
scripts/base.sh.tmpl:
#!/bin/bash echo 'root:${new_root_passwd}' | chpasswd subscription-manager register --org=XXX --activationkey=${satellite_key} && echo '${satellite_key}' > /opt/activationkey_satellite.txt
- 修改
fileprovisioner,用templatefile生成内容:
provisioner "file" { content = templatefile("scripts/base.sh.tmpl", { new_root_passwd = var.new_root_passwd satellite_key = var.satellite_key }) destination = "/tmp/base.sh" connection { type = "ssh" user = var.c_user password = var.d_passwd_user host = var.vm_ip } }
这样传输到远程的base.sh已经是替换好变量的完整脚本,直接运行即可。
2. 通过环境变量传递变量
在remote-exec中先导出环境变量,再用sudo -E保留环境变量运行脚本:
- 修改
remote-exec的inline命令:
provisioner "remote-exec" { inline = [ "echo 'SSH connection successful' > /tmp/1ssh_test_flag", "alias sudo='sudo -S <<< ${var.d_passwd_user}'", "sudo chmod +x /tmp/base.sh", "export NEW_ROOT_PASSWD=${var.new_root_passwd} SATELLITE_KEY=${var.satellite_key}", "sudo -E /tmp/base.sh" ] connection { type = "ssh" user = var.c_user password = var.d_passwd_user host = var.vm_ip } }
- 调整
base.sh,使用环境变量(注意用双引号让bash解析变量):
#!/bin/bash echo "root:$NEW_ROOT_PASSWD" | chpasswd subscription-manager register --org=XXX --activationkey=$SATELLITE_KEY && echo "$SATELLITE_KEY" > /opt/activationkey_satellite.txt
3. 以命令行参数传递变量
在运行脚本时直接把变量作为参数传入,脚本内通过位置参数读取:
- 修改
remote-exec的inline命令:
provisioner "remote-exec" { inline = [ "echo 'SSH connection successful' > /tmp/1ssh_test_flag", "alias sudo='sudo -S <<< ${var.d_passwd_user}'", "sudo chmod +x /tmp/base.sh", "sudo /tmp/base.sh ${var.new_root_passwd} ${var.satellite_key}" ] connection { type = "ssh" user = var.c_user password = var.d_passwd_user host = var.vm_ip } }
- 调整
base.sh,使用位置参数:
#!/bin/bash NEW_ROOT_PASSWD=$1 SATELLITE_KEY=$2 echo "root:$NEW_ROOT_PASSWD" | chpasswd subscription-manager register --org=XXX --activationkey=$SATELLITE_KEY && echo "$SATELLITE_KEY" > /opt/activationkey_satellite.txt
内容的提问来源于stack exchange,提问作者johnmacward
相关产品推荐
相关产品推荐

