如何为Azure虚拟机设置自动定时关机?避免闲置付费咨询
针对你的需求,我整理了几个实用方案,既能实现Azure VM启动后倒计时自动停止(解除分配,这样就不会产生计算费用),还支持手动延长运行时间,完美解决你不想为闲置时段付费又容易忘关机的问题:
方案1:Azure自动化账户 + 本地计时器脚本(推荐,灵活可控)
这个方案结合Azure云端的自动化能力和VM本地的交互计时器,既能保证关机逻辑可靠,又能让你直观看到剩余时间并手动延长。
步骤1:配置Azure自动化账户与关机Runbook
- 先在Azure门户创建一个自动化账户,启用系统托管标识,并给这个标识分配虚拟机参与者权限到目标VM所在的资源组(确保它有权限停止VM)。
- 创建一个PowerShell Runbook,功能是停止指定VM并解除分配:
param( [Parameter(Mandatory=$true)] [string]$VMName, [Parameter(Mandatory=$true)] [string]$ResourceGroupName ) # 停止VM并解除分配(此状态下不产生计算费用) Stop-AzVM -Name $VMName -ResourceGroupName $ResourceGroupName -Force
发布这个Runbook后,先手动测试一次,确认能正常停止你的VM。
步骤2:在Windows 10 VM上编写计时器脚本
在VM本地创建一个PowerShell脚本(比如C:\Scripts\VMRuntimeTimer.ps1),实现启动弹窗倒计时、手动延长、到期触发关机的逻辑:
Add-Type -AssemblyName System.Windows.Forms Add-Type -AssemblyName System.Drawing # 默认设置1小时倒计时(可自行修改为7200秒=2小时) $totalSeconds = 3600 $remainingSeconds = $totalSeconds # 创建计时器窗口 $form = New-Object System.Windows.Forms.Form $form.Text = "VM运行倒计时" $form.Size = New-Object System.Drawing.Size(320,160) $form.StartPosition = "CenterScreen" $form.TopMost = $true # 剩余时间显示标签 $timeLabel = New-Object System.Windows.Forms.Label $timeLabel.Size = New-Object System.Drawing.Size(300,30) $timeLabel.Font = New-Object System.Drawing.Font("Arial",10,[System.Drawing.FontStyle]::Bold) $timeLabel.Text = "剩余运行时间:$([math]::Floor($remainingSeconds/3600))小时$([math]::Floor(($remainingSeconds%3600)/60))分钟" $timeLabel.Location = New-Object System.Drawing.Point(10,15) $form.Controls.Add($timeLabel) # 延长30分钟按钮 $extendBtn = New-Object System.Windows.Forms.Button $extendBtn.Text = "延长30分钟" $extendBtn.Size = New-Object System.Drawing.Size(130,35) $extendBtn.Location = New-Object System.Drawing.Point(10,60) $extendBtn.Add_Click({ $remainingSeconds += 1800 $timeLabel.Text = "剩余运行时间:$([math]::Floor($remainingSeconds/3600))小时$([math]::Floor(($remainingSeconds%3600)/60))分钟" }) $form.Controls.Add($extendBtn) # 倒计时计时器 $timer = New-Object System.Windows.Forms.Timer $timer.Interval = 1000 $timer.Add_Tick({ $remainingSeconds-- if ($remainingSeconds -le 0) { $timer.Stop() $form.Close() # 调用Azure自动化Runbook停止VM $runbookName = "你的Runbook名称" $automationAccount = "你的自动化账户名" $automationRG = "自动化账户所在资源组名" Start-AzAutomationRunbook -AutomationAccountName $automationAccount -Name $runbookName -ResourceGroupName $automationRG -Parameters @{VMName="你的VM名称"; ResourceGroupName="VM所在资源组名"} } else { $timeLabel.Text = "剩余运行时间:$([math]::Floor($remainingSeconds/3600))小时$([math]::Floor(($remainingSeconds%3600)/60))分钟" } }) $timer.Start() $form.ShowDialog()
步骤3:设置脚本开机自启
- 右键脚本,创建快捷方式,修改快捷方式目标为:
powershell.exe -ExecutionPolicy Bypass -File "C:\Scripts\VMRuntimeTimer.ps1" - 把这个快捷方式放到
C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp目录下,这样VM启动时会自动弹出计时器窗口。
方案2:Azure自带自动关机 + 手动延长(极简方案)
如果不需要本地弹窗,只想用Azure原生功能,可以试试这个:
- 在Azure门户找到你的VM,进入自动关机设置,设置每天的关机时间(比如固定在每天10点关机)。但注意这个是固定时间,不是基于VM启动时间的倒计时,适合你启动时间规律的场景。
- 如果你需要延长时间,直接在VM概览页点击取消自动关机,用完后再重新设置即可;也可以用Azure CLI命令快速操作:
# 取消自动关机 az vm auto-shutdown disable --name <你的VM名> --resource-group <资源组名> # 重新设置自动关机(比如2小时后) az vm auto-shutdown enable --name <你的VM名> --resource-group <资源组名> --time 120
方案3:纯本地脚本调用Azure CLI(无需自动化账户)
不想用Azure自动化账户的话,可以在VM本地安装Azure CLI,直接用脚本触发关机:
- 在VM上安装Azure CLI,然后用服务主体非交互式登录(避免每次手动登录):
az login --service-principal -u <服务主体ID> -p <服务主体密码> --tenant <租户ID>
- 修改方案1中的计时器脚本,把调用Runbook的部分替换为Azure CLI命令:
# 停止VM并解除分配 az vm deallocate --name "你的VM名" --resource-group "VM所在资源组名"
- 同样设置开机自启即可。
注意事项
- 不管用哪个方案,都要确保执行关机操作的身份(托管标识/服务主体)有足够的权限停止VM,避免权限不足导致失败。
- 用本地脚本时,建议把服务主体的凭证加密存储,不要明文写在脚本里,比如用Azure Key Vault托管凭证。
内容的提问来源于stack exchange,提问作者user2429448




