Azure VM运行状态查询及自动启动校验脚本优化咨询
解答
一、原有代码的优化方案
原有代码的主要冗余点是重复调用Azure API拉取VM列表、重复执行标签过滤逻辑,频繁的API请求不仅执行效率低,还容易触发Azure接口限流,优化思路如下:
- 提前一次性拉取所有符合
Managed By:Manager标签的VM列表,统计总数后后续循环不需要重复做标签过滤 - 增加轮询等待间隔,避免无间隔高频请求API,默认建议设置30~60秒的间隔
- 合并逻辑减少重复的
Get-AzVM调用,每次轮询只调用一次接口即可同时统计已运行数量
二、超时逻辑实现
我们可以用.NET内置的Stopwatch类做超时计时,设定1800秒(30分钟)的超时阈值,每次循环时先判断是否超过超时时间,触发超时后即可执行自定义的处理逻辑(比如输出告警、发送通知、记录失败日志等)。
完整优化后代码
# 基础配置 $Date = Get-Date -Format "dd-MM-yyyy HH-mm" $ResultsPath = "C:\temp\DailyChecks_$Date.txt" $PollInterval = 30 # 每次轮询间隔,单位秒 $TimeoutSeconds = 1800 # 超时时间30分钟,单位秒 # 提前创建日志目录避免报错 if(-not (Test-Path "C:\temp")){ New-Item -ItemType Directory -Path "C:\temp" | Out-Null } # 登录Azure $Cred = Get-Credential -UserName 'AZ-User' Connect-AzAccount -Tenant 'TenantID' -Credential $Cred | Out-Null # 一次性获取目标VM总数,避免每次过滤标签 $targetVms = Get-AzVM -Status | Where-Object { $_.Tags['Managed By'] -like 'Manager' } $totalCount = $targetVms.Count if($totalCount -eq 0){ Write-Host "未找到符合标签条件的VM,脚本退出" exit 0 } # 启动计时器 $stopwatch = [System.Diagnostics.Stopwatch]::StartNew() $allRunning = $false do { # 单次拉取状态并统计运行中的数量 $runningCount = (Get-AzVM -Status | Where-Object { $_.Tags['Managed By'] -like 'Manager' -and $_.PowerState -eq 'VM running' }).Count Write-Host "当前运行VM数量:$runningCount / 目标总数:$totalCount" if($runningCount -eq $totalCount){ $allRunning = $true Write-Host "所有目标VM均已正常运行,退出轮询" break } # 检查是否超时 if($stopwatch.Elapsed.TotalSeconds -ge $TimeoutSeconds){ Write-Host "脚本执行超时(超过30分钟),未检测到所有VM运行" # 这里写超时后的自定义处理逻辑,比如发送告警、记录错误日志、触发启动操作等 break } # 等待指定时间后再轮询 Start-Sleep -Seconds $PollInterval } while ($true) # 导出最终结果 Get-AzVM -Status | Where-Object { $_.Tags['Managed By'] -like 'Manager' } | Select-Object Name, PowerState | Format-Table | Out-File $ResultsPath Write-Host "检查结果已导出至:$ResultsPath"
补充说明
- 如果需要进一步降低API调用次数,可以提前获取所有目标VM的资源ID,每次轮询时仅查询这些指定VM的状态,进一步减少接口返回数据量
- 超时后的处理逻辑可以根据实际需求扩展,比如调用Azure通信服务发送邮件/短信告警,或者自动调用启动接口拉起未运行的VM
内容的提问来源于stack exchange,提问作者Nuisance
相关产品推荐
相关产品推荐

