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

通过Terraform部署Azure CustomScriptExtension执行磁盘脚本失败

Azure CustomScriptExtension 部署问题解决思路

尝试通过Terraform部署Azure CustomScriptExtension,完成Windows虚拟机的数据磁盘格式化挂载,以及按需扩容C盘,但始终无法将本地脚本传递至虚拟机执行。自定义PowerShell脚本位于Terraform配置同目录的./CustomScripts/CustomScriptDataDisks.ps1,脚本内容如下:

#Custom script to perform format on data disks, assign letter and name based on disk lun

Set-StrictMode -Version 3

try {   
    Write-Output "Change CD drive letter to W"
    Write-Verbose -Message "[Start]::Changing CD drive letter to W..."
    $CDDrive = Get-WmiObject -Class Win32_volume -Filter "DriveType = '5'"
    if ($CDDrive) {$CDDrive | Set-WmiInstance -Arguments @{DriveLetter = 'W:'}}
    Write-Verbose -Message "[Finish]::Changed CD drive letter to W"

    #Extend C drive if necessary
    $CPartition = Get-Partition -DriveLetter C
    $CSupportedSize = Get-PartitionSupportedSize -DriveLetter C
    if ($CSupportedSize.SizeMax -gt $CPartition.Size) {
        Resize-Partition -DriveLetter C -Size $CSupportedSize.SizeMax
    }

    Write-Output "Initializing Disks"
    $disks = Get-Disk | Where-Object partitionstyle -eq 'raw' | Sort-Object number

    if ($disks) {
        #Format disks
        $i = 70
        $DiskCount = 1

        foreach ($disk in $disks) {
            $DiskLUN = [int]([regex]::Match($disk.Path, "[#]{1}\d{1,}[#]{1}").Value.Replace("#", ""))
            if ($DiskLUN -lt 19 -or $DiskLUN -gt 39) { 
                $diskID = [string]$DiskCount                              
                $diskLabel = $env:COMPUTERNAME + "-DataDisk-" + $DiskID
                $diskLetter = [char]$i            

                #Mount Disks
                $disk | 
                Initialize-Disk -PartitionStyle GPT -PassThru |
                New-Partition -UseMaximumSize -DriveLetter $diskLetter |
                Format-Volume -FileSystem NTFS -NewFileSystemLabel $diskLabel -Confirm:$false -Force            

                $i++; $DiskCount++
            }
            if ($DiskLUN -gt 19 -and $DiskLUN -lt 30) {
                $i = 76
                $DiskCount = 1 
                $diskID = [string]$DiskCount                              
                $diskLabel = $env:COMPUTERNAME + "-LogDisk-" + $DiskID
                $diskLetter = [char]$i            

                #Mount Disks
                $disk | 
                Initialize-Disk -PartitionStyle GPT -PassThru |
                New-Partition -UseMaximumSize -DriveLetter $diskLetter |
                Format-Volume -FileSystem NTFS -NewFileSystemLabel $diskLabel -Confirm:$false -Force
                
                $i++; $DiskCount++
            }
            if ($DiskLUN -gt 29 -and $DiskLUN -lt 40) {
                $i = 83
                $DiskCount = 1 
                $diskID = [string]$DiskCount                              
                $diskLabel = $env:COMPUTERNAME + "-BackupDisk-" + $DiskID
                $diskLetter = [char]$i            

                #Mount Disks
                $disk | 
                Initialize-Disk -PartitionStyle GPT -PassThru |
                New-Partition -UseMaximumSize -DriveLetter $diskLetter |
                Format-Volume -FileSystem NTFS -NewFileSystemLabel $diskLabel -Confirm:$false -Force
                
                $i++; $DiskCount++
            }
        }
    }
} #end try
catch {
    Write-Error -Message "Caught an exception:"
    Write-Error -Message "Exception Type: $($_.Exception.GetType().FullName)"
    Write-Error -Message "Exception Message: $($_.Exception.Message)"
}

已尝试的方案及错误

方案1:使用相对路径指定脚本

配置如下:

resource "azurerm_virtual_machine_extension" "CustomScriptDisks" {
  name                 = "${azurerm_windows_virtual_machine.win-vm.name}-CustomScriptDisks"
  virtual_machine_id   = azurerm_windows_virtual_machine.win-vm.id
  publisher            = "Microsoft.Compute"
  type                 = "CustomScriptExtension"
  type_handler_version = "1.10"

  settings = <<SETTINGS
    {
        "commandToExecute": "powershell.exe -ExecutionPolicy Unrestricted -File ./CustomScripts/CustomScriptDataDisks.ps1"
    }
  SETTINGS
}

错误信息:

Command execution finished, but failed because it returned a non-zero exit code of: '-196608'. The command had an error output of: 'The argument './CustomScripts/CustomScriptDataDisks.ps1' to the -File parameter does not exist. Provide the path to an existing '.ps1' file as an argument to the -File parameter. '

方案2:Base64编码脚本嵌入配置

配置如下:

resource "azurerm_virtual_machine_extension" "CustomScriptDisks" {
  name                 = "${azurerm_windows_virtual_machine.win-vm.name}-CustomScriptDisks"
  virtual_machine_id   = azurerm_windows_virtual_machine.win-vm.id
  publisher            = "Microsoft.Compute"
  type                 = "CustomScriptExtension"
  type_handler_version = "1.10"

  protected_settings = <<SETTINGS
  {
     "commandToExecute": "powershell -encodedCommand ${textencodebase64(file("./CustomScripts/CustomScriptDataDisks.ps1"), "UTF-16LE")}"
  }
  SETTINGS
} 

错误信息:

Command execution finished, but failed because it returned a non-zero exit code of: '1'. The command had an error output of: 'The command line is too long. '

解决思路

1. 使用fileUris从存储账户下载脚本

将PowerShell脚本上传至Azure存储账户的blob容器(可设置公开访问或生成SAS令牌),在Terraform配置中通过settings指定脚本的存储URL,commandToExecute直接引用下载后的脚本文件名(默认下载路径为C:\Packages\Plugins\Microsoft.Compute.CustomScriptExtension\<version>\Downloads\0\,可直接用文件名)。

示例配置:

resource "azurerm_virtual_machine_extension" "CustomScriptDisks" {
  name                 = "${azurerm_windows_virtual_machine.win-vm.name}-CustomScriptDisks"
  virtual_machine_id   = azurerm_windows_virtual_machine.win-vm.id
  publisher            = "Microsoft.Compute"
  type                 = "CustomScriptExtension"
  type_handler_version = "1.10"

  settings = <<SETTINGS
    {
        "fileUris": ["https://yourstorageaccount.blob.core.windows.net/yourcontainer/CustomScriptDataDisks.ps1"],
        "commandToExecute": "powershell.exe -ExecutionPolicy Unrestricted -File CustomScriptDataDisks.ps1"
    }
  SETTINGS

  # 若使用私有容器,添加存储账户密钥或SAS令牌
  protected_settings = <<PROTECTED_SETTINGS
    {
        "storageAccountName": "yourstorageaccount",
        "storageAccountKey": "yourstoragekey"
    }
  PROTECTED_SETTINGS
}

2. 精简脚本并优化编码

  • 移除脚本中不必要的注释、冗余空格,合并重复逻辑,缩小脚本体积
  • 使用trimspace()处理脚本内容后再编码,减少冗余字符

示例:

"commandToExecute": "powershell -encodedCommand ${textencodebase64(trimspace(file("./CustomScripts/CustomScriptDataDisks.ps1")), "UTF-16LE")}"

3. 更新扩展版本至最新稳定版

将type_handler_version更新为最新稳定版(如1.14),新版本通常优化了命令行长度限制和脚本传递逻辑。

4. 本地预生成编码内容

提前在本地用PowerShell将脚本编码为Base64:

[Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes((Get-Content -Path ./CustomScripts/CustomScriptDataDisks.ps1 -Raw)))

将编码结果保存为文本文件,在Terraform中直接读取该文件内容,避免配置中生成过长字符串。

示例:

resource "azurerm_virtual_machine_extension" "CustomScriptDisks" {
  # 其他配置保持不变
  protected_settings = <<SETTINGS
  {
     "commandToExecute": "powershell -encodedCommand ${file("./CustomScripts/encoded_script.txt")}"
  }
  SETTINGS
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 14:56:00