使用 Azure PowerShell 同时停止多个 Azure VM

Posted

技术标签:

【中文标题】使用 Azure PowerShell 同时停止多个 Azure VM【英文标题】:Stop multiple Azure VMs at the same time using Azure PowerShell 【发布时间】:2017-02-02 06:18:17 【问题描述】:
Get-AzureRmVM -ResourceGroupName RG-VNETS | 
    ForEach-Object  
        Get-AzureRmVM -ResourceGroupName RG-VNETS -Name $_.Name -Status 
     | 
    ForEach-Object  
        if (-Not ($_.Statuses[1].DisplayStatus -like "*deallocated*"))  
            Stop-AzureRmVM -ResourceGroupName RG-VNETS -Name $_.Name -Force 
         
    

我有一个停止我所有 Azure VM 的脚本,这里的问题是这个脚本一次关闭一个 VM。

即如果我有三个虚拟机:VM1、VM2、VM3

在 VM1 完全关闭之前,脚本不会关闭 VM2,依此类推。我不知道是否有办法告诉 PowerShell 不要等待每个 VM 完全关闭才能继续执行以下操作。

【问题讨论】:

【参考方案1】:

GitHub 上已经有一个 feature request 用于异步执行此类操作,应该在不久的将来实现。

与此同时,您可以使用 PoshRSJob 模块执行如下解决方法 - 只需将 temp4so 替换为您的资源组名称

# Install PoshRSJob if necessary
#
# Install-Module PoshRSJob

Login-AzureRmAccount    

$start = Get-Date
$jobs = Get-AzureRmVM -ResourceGroupName temp4so | 
    %  
        Get-AzureRmVM -ResourceGroupName temp4so -Name $_.Name -Status 
     | 
    %  
        if (-Not ($_.Statuses[1].DisplayStatus -like "*deallocated*"))  
            $vm = $_
            Start-RSJob                
                Stop-AzureRmVM -ResourceGroupName temp4so -Name ($using:vm).Name -Force
            
        
    
$jobs | Wait-RSJob | Receive-RSJob
$jobs | Remove-RSJob
$end = Get-Date
Write-Host ("Stopping took 0" -f ($end - $start))

在我的带有 3 个虚拟机的测试用例中,输出类似于以下内容,表明操作是并行完成的

OperationId : 
Status      : Succeeded
StartTime   : 24.09.2016 18:49:10
EndTime     : 24.09.2016 18:51:32
Error       : 

OperationId : 
Status      : Succeeded
StartTime   : 24.09.2016 18:49:11
EndTime     : 24.09.2016 18:51:22
Error       : 

OperationId : 
Status      : Succeeded
StartTime   : 24.09.2016 18:49:11
EndTime     : 24.09.2016 18:51:22
Error       : 

Stopping took 00:02:32.9115538

注意:您不能简单地使用标准 Start-Job 来卸载同步。对后台作业的操作,因为在后台新创建的 PowerShell 实例不会与您的初始会话共享上下文,因此需要您为每个会话再次进行身份验证。由于 PoshRSJob 在初始 PowerShell 实例中使用 PowerShell 运行空间,因此不需要再次进行身份验证。

【讨论】:

非常感谢,它正是我所需要的。我刚刚测试了它,它可以工作 无论我运行多少次,这个脚本只会停止前 5 个虚拟机。无论如何要关闭所有虚拟机? @WinBoss,您只看到一些虚拟机关闭的原因有两个(我可以看到)。 1. 你有不同资源组中的虚拟机吗?此脚本一次仅针对一个资源组。 2. 您使用的是经典部署还是资源管理器部署?如果是这样,示例脚本正在使用 RM 模块。只需将它们切换到 Get-AzureVM、Stop-AzureVM 等经典模块即可。更多信息请参见:docs.microsoft.com/en-us/azure/azure-resource-manager/… 是的,我正在使用多个资源组和 RM 模型。有什么方法可以停止所有资源组中的所有虚拟机?【参考方案2】:

他们根据 DAXaholic 链接的 GitHub 功能请求实现了 -AsJob。这是一个来自 GitHub cmets 部分的示例。

$VMList = Get-AzureRmVM -ResourceGroupName $resourceGroupName
$JobList = @()
foreach ($vm in $VMList) 
  $JobList += Stop-AzureRmVm -ResourceGroupName $resourceGroupName -Name $vm -Force -AsJob | Add-Member -MemberType NoteProperty -Name VMName -Value $vm.Name -PassThru

如果您想等待作业完成并进行清理:

$JobList | Wait-Job | Receive-Job
$JobList | Remove-Job

【讨论】:

以上是关于使用 Azure PowerShell 同时停止多个 Azure VM的主要内容,如果未能解决你的问题,请参考以下文章

当资源组上有删除锁时,如何使用 Powershell 停止 Azure 数据工厂的存储事件触发器?

使用 PowerShell 自动登录Azure

使用 PowerShell 自动登录 Azure

Azure 基础:用 PowerShell 自动登录

在Azure上通过Powershell创建多Interface的Cisco CSR路由器

Azure通过Powershell,创建虚拟机镜像