Terraform部署Azure VM后执行Bash脚本失败求助
我来帮你梳理下你遇到的两个核心问题,然后给出具体的可落地解决方案:
问题1:custom_data未生成脚本也未执行
你提到使用custom_data时,脚本文件找不到也没执行,这是因为CentOS的cloud-init默认不会自动将纯脚本内容转成可执行文件。默认情况下,custom_data的内容会被base64解码后保存到/var/lib/cloud/instance/user-data.txt,但不会自动执行,也不会帮你生成独立的脚本文件——除非你按照cloud-init的标准配置格式来编写内容。
解决方案:用cloud-init格式配置custom_data
修改你的azurerm_virtual_machine资源中的os_profile部分,使用cloud-init的write_files模块将脚本写入到VM内的指定路径,再通过runcmd指令执行它:
os_profile { computer_name = var.middleware_vm admin_username = "middlewareadmin" custom_data = <<CUSTOM_DATA #cloud-config write_files: - content: | ${file("scripts/middleware_disk.sh")} path: /tmp/middleware_disk.sh permissions: '0755' runcmd: - /tmp/middleware_disk.sh CUSTOM_DATA }
这样cloud-init会在VM启动时自动完成三件事:
- 把本地
scripts/middleware_disk.sh的内容写入到VM内的/tmp/middleware_disk.sh - 给脚本设置可执行权限
- 执行这个脚本
如果需要调试,可以查看VM内的/var/log/cloud-init.log和/var/log/cloud-init-output.log日志文件。
问题2:azurerm_virtual_machine_extension无法上传本地文件
你提到CustomScript Extension不支持直接上传本地文件(且受需求限制不能用fileUris),那我们可以将本地脚本内容直接嵌入到commandToExecute中,先在VM内创建脚本文件再执行。
解决方案:在Extension中嵌入脚本内容
修改你的azurerm_virtual_machine_extension资源,用bash的heredoc语法将本地脚本内容写入到VM内的文件,然后执行:
resource "azurerm_virtual_machine_extension" "test" { name = "hostname" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name virtual_machine_name = azurerm_virtual_machine.test.name publisher = "Microsoft.Azure.Extensions" type = "CustomScript" type_handler_version = "2.0" settings = jsonencode({ commandToExecute = <<EOT bash -c 'cat > /tmp/my_script.sh <<"SCRIPT" ${file("scripts/my_script.sh")} SCRIPT chmod +x /tmp/my_script.sh /tmp/my_script.sh' EOT }) tags = { environment = "Production" } }
这里的关键细节是:
- 使用
<<\"SCRIPT\"来避免bash解析脚本中的特殊字符(比如变量、引号) - 先创建脚本文件、赋予执行权限,再执行脚本
你可以在Azure Portal的VM扩展页面查看执行日志,或者通过az vm extension show命令获取执行状态。
两种方法的选择建议
- cloud-init(custom_data):适合VM启动阶段的初始化配置,不需要额外的Azure资源,执行时机早,但调试需要查看VM内的日志。
- CustomScript Extension:适合VM部署完成后的后续配置或更新,有Azure层面的日志监控,执行时机更灵活,还可以重复执行。
内容的提问来源于stack exchange,提问作者Mario Jacobo

