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

如何为Azure虚拟机编写补丁前置/后置PowerShell脚本?

Azure补丁系统前置/后置脚本优化与疑问解答

核心需求

  • 前置脚本:给DEV/UAT环境的AVD虚拟机加AutoScaleIgnore=Patching标签,再启动这些虚拟机
  • 后置脚本:补丁完成后重启当前虚拟机,移除AutoScaleIgnore=Patching标签
  • 疑问:之前看到开机脚本用了函数,这有必要吗?刚学PowerShell,想搞懂代码写法和运行逻辑

关于“是否需要用函数”的说明

不是必须,但用函数有明显好处:

  • 复用性强:后续如果要多次执行开机、标签操作,不用重复写相同代码
  • 可读性更高:函数名(比如Start-TargetVMs)直接说明功能,逻辑一目了然
  • 方便维护调试:可以单独测试函数功能,定位问题更简单
  • 新手先写线性代码完全没问题,后续慢慢重构为函数是很好的学习过程

现有代码问题分析与优化

前置脚本(原代码问题)

  1. Connect-AzAccount语法错误:-Tenant参数后缺空格,参数顺序也不对
  2. $tags未初始化就用+=,会直接报错
  3. New-AZTag拼写错误:ResouceGroupName应为ResourceGroupName,且New-AzTag会覆盖原有标签,应该用Update-AzTag -Operation Merge保留原有标签
  4. VM筛选条件可以简化,不用写重复的$_.Tags['AVD'] -eq "AVD"
  5. 开机部分重复查询VM,完全可以复用前面的变量

优化后的前置脚本

##########################  前置脚本 - 添加标签并开机VM  ##################################
# 加载凭据并连接Azure
$credentials = Import-Clixml -Path "xxxxx" # 替换为实际凭据文件路径
Connect-AzAccount -Tenant "xxxxx-xxxxx-xxxxx-xxx-xxxxxxxx" -Credential $credentials # 修正语法错误
Set-AzContext -Subscription "xxxxx" # 替换为实际订阅ID

# 定义要添加的标签(先初始化哈希表,避免未声明报错)
$patchTag = @{AutoScaleIgnore = "Patching"}

# 获取DEV/UAT环境的AVD虚拟机
$targetVMs = Get-AzVM | Where-Object {
    $_.Tags['AVD'] -eq "AVD" -and $_.Tags['Environment'] -in "DEV", "UAT"
}

# 为目标VM添加标签(保留原有标签,仅新增指定标签)
foreach ($vm in $targetVMs) {
    Update-AzTag -ResourceId $vm.Id -Tag $patchTag -Operation Merge
    Write-Host "已为VM [$($vm.Name)] 添加标签 AutoScaleIgnore=Patching"
}

# 启动目标VM(直接复用前面的$targetVMs,无需重新查询)
foreach ($vm in $targetVMs) {
    # 先检查VM状态,避免重复启动
    $vmStatus = Get-AzVM -Name $vm.Name -ResourceGroupName $vm.ResourceGroupName -Status
    if ($vmStatus.Statuses[1].Code -notlike "PowerState/running") {
        Start-AzVM -Name $vm.Name -ResourceGroupName $vm.ResourceGroupName -NoWait
        Write-Host "已启动VM [$($vm.Name)]"
    } else {
        Write-Host "VM [$($vm.Name)] 已处于运行状态,无需启动"
    }
}

后置脚本(原代码问题)

  1. 重复获取当前VM:$a = $env:computername后又重新赋值为Get-AzVM,可以合并成一行
  2. $tags未初始化直接+=,会报错
  3. 可以加简单的错误处理,避免因VM不存在或权限问题直接崩溃

优化后的后置脚本

##########################  后置脚本 - 重启VM并移除标签  ##################################
# 加载凭据并连接Azure
$credentials = Import-Clixml -Path "xxxxx" # 替换为实际凭据文件路径
Connect-AzAccount -Tenant "xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx" -Credential $credentials
Set-AzContext -Subscription "xxxxx" # 替换为实际订阅ID

# 获取当前运行脚本的VM
$currentVM = Get-AzVM -Name $env:COMPUTERNAME -ErrorAction Stop

# 重启VM
Restart-AzVM -Name $currentVM.Name -ResourceGroupName $currentVM.ResourceGroupName -Confirm:$false
Write-Host "已触发VM [$($currentVM.Name)] 重启"

# 移除AutoScaleIgnore=Patching标签
$tagToRemove = @{AutoScaleIgnore = "Patching"}
Update-AzTag -ResourceId $currentVM.Id -Tag $tagToRemove -Operation Delete -ErrorAction SilentlyContinue
Write-Host "已移除VM [$($currentVM.Name)] 的 AutoScaleIgnore=Patching 标签"

代码运行逻辑说明

前置脚本逻辑

  1. 身份验证:导入保存的凭据文件,连接到指定Azure租户和订阅
  2. 筛选目标VM:查询所有带AVD=AVD标签、环境为DEV/UAT的虚拟机
  3. 添加标签:遍历目标VM,用Update-AzTag合并新增标签,不覆盖原有标签
  4. 启动VM:先检查VM状态,只启动未运行的VM,避免无效操作

后置脚本逻辑

  1. 身份验证:同前置脚本,确保有权限操作Azure资源
  2. 获取当前VM:通过$env:COMPUTERNAME拿到运行脚本的虚拟机对象
  3. 重启VM:触发虚拟机重启操作
  4. 移除标签:用Update-AzTag的Delete操作,删除指定的标签键值对

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 18:35:51