如何在Azure Terraform中优雅使用azurerm_virtual_machine_extension执行多命令
优雅地在Azure VM扩展中执行多行Linux命令
你可以通过以下几种方式替代&&堆砌命令的写法,让代码更易读和维护:
方法1:在HCL中拆分命令行(保留JSON字符串格式)
利用HCL的多行字符串特性,将命令拆分为多行,同时用\连接HCL中的行(确保JSON字符串是连续的),bash会正确识别命令链:
resource "azurerm_virtual_machine_extension" "run_command" { for_each = var.vm_template name = "${each.value.vm_name}-run_command" virtual_machine_id = azurerm_linux_virtual_machine.vm[each.key].id publisher = "Microsoft.Azure.Extensions" type = "CustomScript" type_handler_version = "2.0" timeouts { create = "1h" # VM数量多的话耗时更长 } settings = <<SETTINGS { "commandToExecute": "bash -c 'hostnamectl set-hostname --static ${each.value.hostname} && \\ sleep 60 && \\ sh /tmp/for_image.sh > /tmp/installed.log 2>&1'" } SETTINGS }
方法2:嵌入临时脚本(通过bash here-doc)
将多行命令写入临时脚本文件再执行,避免长命令串:
resource "azurerm_virtual_machine_extension" "run_command" { for_each = var.vm_template name = "${each.value.vm_name}-run_command" virtual_machine_id = azurerm_linux_virtual_machine.vm[each.key].id publisher = "Microsoft.Azure.Extensions" type = "CustomScript" type_handler_version = "2.0" timeouts { create = "1h" } settings = <<SETTINGS { "commandToExecute": "bash -c 'cat <<EOF > /tmp/setup.sh && chmod +x /tmp/setup.sh && /tmp/setup.sh hostnamectl set-hostname --static ${each.value.hostname} sleep 60 sh /tmp/for_image.sh > /tmp/installed.log 2>&1 EOF'" } SETTINGS }
这里利用HCL heredoc特性保留换行,bash会将here-doc内容写入临时脚本并执行。
方法3:使用外部脚本文件(最推荐)
将命令写入独立的shell脚本,上传到Azure Blob Storage,通过CustomScript扩展拉取执行。这种方式适合复杂命令集,便于版本控制和维护:
步骤1:创建外部脚本(setup.sh)
#!/bin/bash TARGET_HOSTNAME=$1 hostnamectl set-hostname --static $TARGET_HOSTNAME sleep 60 sh /tmp/for_image.sh > /tmp/installed.log 2>&1
步骤2:更新Terraform配置
resource "azurerm_virtual_machine_extension" "run_command" { for_each = var.vm_template name = "${each.value.vm_name}-run_command" virtual_machine_id = azurerm_linux_virtual_machine.vm[each.key].id publisher = "Microsoft.Azure.Extensions" type = "CustomScript" type_handler_version = "2.0" timeouts { create = "1h" } settings = <<SETTINGS { "fileUris": ["https://your-storage-account.blob.core.windows.net/scripts/setup.sh"], "commandToExecute": "bash setup.sh ${each.value.hostname}" } SETTINGS protected_settings = <<PROTECTED_SETTINGS { "storageAccountName": "your-storage-account-name", "storageAccountKey": "${azurerm_storage_account.your_sa.primary_access_key}" } PROTECTED_SETTINGS }
这种方式将命令逻辑与Terraform配置分离,脚本可单独编辑、测试,大幅提升可维护性。
内容的提问来源于stack exchange,提问作者gotothesky
相关产品推荐
相关产品推荐

