You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Terraform的remote-exec中使用file()写入authorized_keys崩溃如何解决

问题根因
  1. 命令语法错误:adduser语句中/home/username与后续--gecos参数之间缺失空格,会导致用户创建命令直接执行失败。
  2. 重定向权限问题:sudo echo ${xxx} > 目标路径的写法本身不生效,sudo仅对echo命令提权,文件写入的重定向操作由当前普通用户权限的shell执行,无权限写入其他用户的.ssh目录。
  3. 字符串转义冲突:多层双引号嵌套+公钥内容插值的组合,会让Terraform解析阶段或远端shell执行阶段出现语法错误,严重时触发崩溃。
  4. 路径不严谨:使用~/../username的相对路径依赖执行环境的当前用户目录,存在解析失败的风险。
修复方案

方案1:直接修正现有写法

采用tee替代echo+重定向,配合heredoc避免转义冲突,修改后的inline代码块如下:

inline = [
  # 修正adduser参数空格,用绝对路径指定用户home目录
  "sudo adduser --quiet --disabled-password --shell /bin/bash --home /home/username --gecos \"Firstname Lastname\" username",
  "sudo mkdir -p /home/username/.ssh",
  "sudo chmod 700 /home/username/.ssh",
  # heredoc包裹公钥写入逻辑,避免转义问题,tee自带提权写入能力
  <<EOT
  sudo tee /home/username/.ssh/authorized_keys <<'EOF'
  ${file("userKeys/username.pub")}
EOF
EOT,
  "sudo chmod 600 /home/username/.ssh/authorized_keys",
  # 修正用户组语法,用:替代.兼容所有Linux版本
  "sudo chown -R username:username /home/username/.ssh"
]

方案2:更稳定的环境变量传参方案

把公钥内容提前注入到remote-exec的环境变量中,彻底避免插值和转义冲突:

provisioner "remote-exec" {
  environment = {
    USER_SSH_PUB_KEY = file("userKeys/username.pub")
  }
  inline = [
    "sudo adduser --quiet --disabled-password --shell /bin/bash --home /home/username --gecos \"Firstname Lastname\" username",
    "sudo mkdir -p /home/username/.ssh",
    "sudo chmod 700 /home/username/.ssh",
    "echo \"$USER_SSH_PUB_KEY\" | sudo tee /home/username/.ssh/authorized_keys",
    "sudo chmod 600 /home/username/.ssh/authorized_keys",
    "sudo chown -R username:username /home/username/.ssh"
  ]
}
file()函数在remote-exec中使用的合理性

是合理方案。file()是Terraform本地执行的函数,会在apply阶段提前读取本地指定路径的文件内容,插值到命令中后再传给远端虚拟机执行,公钥这种小体积文本完全适用,仅需注意不要用file()读取MB级以上的大文件,避免命令过长导致执行失败。

内容的提问来源于stack exchange,提问作者ToolKiD

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.21 21:06:04