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

求助:创建Azure自动化Runbook实现VM启动后执行本地/Blob脚本

解决Azure Automation Runbook启动VM后执行脚本的问题

Hey Tom, 我完全懂你现在的困扰——VM能正常启动,但后续的登录和脚本执行环节总掉链子,这种情况我帮不少人排查过。下面给你整理两种最实用的实现方案,一步步来,应该能搞定你的问题:


方案一:用Invoke-AzVMRunCommand(推荐!依赖更少更稳定)

这个方法是Azure原生的VM命令执行方式,不需要直接建立WinRM连接,靠Azure VM扩展就能完成脚本执行,适合大多数场景。

前提准备

  • 你的VM已经默认安装了Azure VM扩展(新建VM一般自带,老VM可以手动安装)
  • 自动化账户的Run As账户需要有VM的Contributor权限,以及Microsoft.Compute/virtualMachines/runCommand/action权限
  • 如果脚本存在Blob存储,要生成带读取权限的SAS URL,或者给VM配置Managed Identity让它能访问Blob

Runbook代码示例

# 用Run As账户登录Azure
$connectionName = "AzureRunAsConnection"
try {
    $servicePrincipalConnection = Get-AutomationConnection -Name $connectionName         

    Connect-AzAccount `
        -ServicePrincipal `
        -TenantId $servicePrincipalConnection.TenantId `
        -ApplicationId $servicePrincipalConnection.ApplicationId `
        -CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint 
}
catch {
    if (!$servicePrincipalConnection) {
        $ErrorMessage = "找不到连接 '$connectionName'."
        throw $ErrorMessage
    } else{
        Write-Error -Message $_.Exception
        throw $_.Exception
    }
}

# 自定义参数:替换成你的资源信息
$vmName = "你的VM名称"
$resourceGroupName = "你的资源组名称"
# 可选:VM本地脚本路径 或 Blob SAS URL
$localScriptPath = "C:\Scripts\你的脚本.ps1"
$blobScriptUri = "https://你的存储账户.blob.core.windows.net/容器名/脚本.ps1?SAS参数"

# 启动VM
Start-AzVM -Name $vmName -ResourceGroupName $resourceGroupName

# 等待VM完全就绪(避免刚启动就执行脚本)
do {
    $vmStatus = Get-AzVM -Name $vmName -ResourceGroupName $resourceGroupName -Status
    Write-Output "当前VM状态:$($vmStatus.Statuses[1].DisplayStatus)"
    Start-Sleep -Seconds 30
} while ($vmStatus.Statuses[1].DisplayStatus -ne "VM running")

# 执行VM本地脚本
Invoke-AzVMRunCommand `
    -ResourceGroupName $resourceGroupName `
    -Name $vmName `
    -CommandId 'RunPowerShellScript' `
    -ScriptPath $localScriptPath

# 如果要执行Blob里的脚本,替换成下面的命令
# Invoke-AzVMRunCommand `
#     -ResourceGroupName $resourceGroupName `
#     -Name $vmName `
#     -CommandId 'RunPowerShellScript' `
#     -ScriptUri $blobScriptUri

注意事项

  • RunCommand默认用系统账户执行,自带管理员权限,不需要额外配置
  • Blob的SAS URL要设置足够长的过期时间,并且只开放读取权限
  • 如果执行失败,先看Runbook的详细日志,里面会明确指出是权限问题还是脚本本身的错误

方案二:用Invoke-Command(适合需要直接交互的场景)

这个方法需要建立WinRM连接到VM,适合需要在VM上执行复杂交互操作的情况,但配置步骤更多。

前提准备

  • VM已开启WinRM服务(Azure VM默认开启,自定义镜像可能需要手动配置)
  • NSG规则要允许WinRM端口(5985 HTTP / 5986 HTTPS)
  • 自动化账户已存储VM的本地管理员凭据(就是你提到的个人凭据)
  • 如果用私有IP连接,自动化账户的Hybrid Worker需要和VM在同一个VNet,或者通过VPN/ExpressRoute访问

Runbook代码示例

# 用Run As账户登录Azure
$connectionName = "AzureRunAsConnection"
try {
    $servicePrincipalConnection = Get-AutomationConnection -Name $connectionName         

    Connect-AzAccount `
        -ServicePrincipal `
        -TenantId $servicePrincipalConnection.TenantId `
        -ApplicationId $servicePrincipalConnection.ApplicationId `
        -CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint 
}
catch {
    if (!$servicePrincipalConnection) {
        $ErrorMessage = "找不到连接 '$connectionName'."
        throw $ErrorMessage
    } else{
        Write-Error -Message $_.Exception
        throw $_.Exception
    }
}

# 自定义参数
$vmName = "你的VM名称"
$resourceGroupName = "你的资源组名称"
$credentialName = "自动化账户里存储的凭据名称"
$localScriptPath = "C:\Scripts\你的脚本.ps1"
$blobScriptUrl = "https://你的存储账户.blob.core.windows.net/容器名/脚本.ps1"

# 启动VM并等待就绪
Start-AzVM -Name $vmName -ResourceGroupName $resourceGroupName
do {
    $vmStatus = Get-AzVM -Name $vmName -ResourceGroupName $resourceGroupName -Status
    Write-Output "当前VM状态:$($vmStatus.Statuses[1].DisplayStatus)"
    Start-Sleep -Seconds 30
} while ($vmStatus.Statuses[1].DisplayStatus -ne "VM running")

# 获取VM的私有IP(用公网IP的话替换成PublicIpAddress)
$vmNicId = (Get-AzVM -Name $vmName -ResourceGroupName $resourceGroupName).NetworkProfile.NetworkInterfaces[0].Id
$privateIp = (Get-AzNetworkInterface -ResourceId $vmNicId).IpConfigurations.PrivateIpAddress

# 获取存储的VM凭据
$vmCred = Get-AutomationPSCredential -Name $credentialName

# 创建WinRM会话(自签证书需要跳过校验)
$sessionOptions = New-PSSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck
$vmSession = New-PSSession -ComputerName $privateIp -Credential $vmCred -SessionOption $sessionOptions

# 执行VM本地脚本
Invoke-Command -Session $vmSession -FilePath $localScriptPath

# 如果执行Blob脚本:先下载到VM再执行
# Invoke-Command -Session $vmSession -ScriptBlock {
#     Invoke-WebRequest -Uri $using:blobScriptUrl -OutFile "C:\temp\临时脚本.ps1"
#     & "C:\temp\临时脚本.ps1"
# }

# 关闭会话
Remove-PSSession $vmSession

注意事项

  • 生产环境建议给WinRM配置正式SSL证书,不要一直用跳过校验的参数
  • 如果连接失败,先检查NSG端口是否开放、VM的防火墙是否允许WinRM流量
  • 凭据必须是VM本地的管理员账户,否则没有执行权限

额外排查小技巧

  1. 先在本地PowerShell里模拟执行脚本,排除脚本本身的语法错误
  2. 查看Runbook的详细日志,里面会有具体的错误代码和描述,比如权限不足、连接超时等
  3. 优先尝试方案一,因为它依赖更少,不需要配置WinRM,稳定性更高

内容的提问来源于stack exchange,提问作者Tom Djernæs

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:39:34