在Azure上的特定资源组中停止/启动VM

问题描述

这是脚本:因为我是云基础设施自动化的新手,所以我一直坚持下去。我基本上是在尝试根据VM的电源状态将VM收集的详细信息添加到单独的列表中。

工作流程rg-startstop {

param(
    [string]$power,[string]$azureResourceGroup
    )
       
    $connectionName = "AzureRunAsConnection"
    try
    {
        # Get the connection "AzureRunAsConnection "
        $servicePrincipalConnection=Get-AutomationConnection -Name $connectionName         
    
        "Logging in to Azure..."
        Add-AzureRmAccount `
            -ServicePrincipal `
            -TenantId $servicePrincipalConnection.TenantId `
            -ApplicationId $servicePrincipalConnection.ApplicationId `
            -CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint 
    }
    catch 
    {
        if (!$servicePrincipalConnection)
        {
            $ErrorMessage = "Connection $connectionName not found."
            throw $ErrorMessage
        } else{
            Write-Error -Message $_.Exception
            throw $_.Exception
        }
    }
    
   
    $vms = Get-AzureRMVM -ResourceGroupName $azureResourceGroup  
    $vmrunninglist = @()
    $vmstoppedlist = @()
    
    
    Foreach($vm in $vms)
        {
            $vmstatus = Get-AzureRMVM -ResourceGroupName $azureResourceGroup -name $vm.name -Status       
            $PowerState = (get-culture).TextInfo.ToTitleCase(($vmstatus.statuses)[1].code.split("/")[1])
              
          
            if ($Powerstate -eq 'Running')
            {  
                $vmrunninglist = $vmrunninglist + $vm.name
            }
            if ($Powerstate -eq 'Deallocated')
            {
                $vmstoppedlist = $vmstoppedlist + $vm.name
            } 
        }
    
                
    if ($power -eq 'start') {
       
       foreach ($vm in $vmrunninglist) {
        Start-AzureRmVM -ResourceGroupName $azureResourceGroup -Name $vm.name -Verbose
       }

    }
        
    
    if ($power -eq 'stop') {
        foreach ($vm in $vmstoppedlist) {
            Stop-AzureRmVM -ResourceGroupName $azureResourceGroup -Name $vm.name -Verbose -Force
           }
    }
         
    
}
    
    
    
    

错误是:您不能在空值表达式上调用方法。 因此,请有人可以对此进行修改吗?

解决方法

请检查$vm$vms$vmstatus(get-culture)(get-culture).TextInfo.ToTitleCase(($vmstatus.statuses)[1](get-culture).TextInfo.ToTitleCase(($vmstatus.statuses)[1].code [1中的(get-culture).TextInfo.ToTitleCase(($vmstatus.statuses)[1].code.split("/")的值]通过添加try catch。其中一个/很少为空。

,

欢迎使用堆栈溢出。 :)

通常,如果您尝试使用任何方法对空值表达式进行某些操作,都会生成错误“ you cannot call a method on a null-valued expression”。我相信在这种情况下,表达式为($vmstatus.statuses)[1].code,方法为split

出于测试目的,如果尝试拆分不存在的($vmstatus.statuses)[2].code,则会看到相同的空值表达式错误,如下所示。

enter image description here

因此,要回答有关如何修改此问题的问题,请在我的设置中找到以下更新的脚本。

param(
    [string]$power,[string]$azureResourceGroup
    )
       
    $connectionName = "AzureRunAsConnection"
    try
    {
        # Get the connection "AzureRunAsConnection "
        $servicePrincipalConnection=Get-AutomationConnection -Name $connectionName         
    
        "Logging in to Azure..."
        Add-AzureRmAccount `
            -ServicePrincipal `
            -TenantId $servicePrincipalConnection.TenantId `
            -ApplicationId $servicePrincipalConnection.ApplicationId `
            -CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint 
    }
    catch 
    {
        if (!$servicePrincipalConnection)
        {
            $ErrorMessage = "Connection $connectionName not found."
            throw $ErrorMessage
        } else{
            Write-Error -Message $_.Exception
            throw $_.Exception
        }
    }
    
   
    $vms = Get-AzureRMVM -ResourceGroupName $azureResourceGroup  
    $vmrunninglist = @()
    $vmstoppedlist = @()
    
    
    Foreach($vm in $vms)
        {
            $vmstatus = Get-AzureRMVM -ResourceGroupName $azureResourceGroup -name $vm.name -Status       
            
            #$PowerState = (get-culture).TextInfo.ToTitleCase(($vmstatus.statuses)[1].code.split("/")[1])
            $vmstatusescodes = $vmstatus.Statuses.code
            
            Foreach($vmstatusescode in $vmstatusescodes)
            {
                if($vmstatusescode -eq "PowerState/deallocated")
                {
                    $vmstoppedlist = $vmstoppedlist + $vm.name
                }
                elseif($vmstatusescode -eq "PowerState/running")
                {
                    $vmrunninglist = $vmrunninglist + $vm.name
                }
            }
        }
    
                
    if ($power -eq 'start') {
       
       foreach ($vm in $vmrunninglist) {
        Start-AzureRmVM -ResourceGroupName $azureResourceGroup -Name $vm.name -Verbose
       }

    }
        
    
    if ($power -eq 'stop') {
        foreach ($vm in $vmstoppedlist) {
            Stop-AzureRmVM -ResourceGroupName $azureResourceGroup -Name $vm.name -Verbose -Force
           }
    }
         
    
}

这里脚本的变化是,我们删除了对

的依赖
  1. $vmstatus.statuses.code数组(因为不存在的第一个数组元素是您看到空值表达式错误的原因)
  2. split方法
  3. Get-Culture cmdlet(在这种情况下实际上并不需要使用)

您始终可以通过添加越来越多的错误处理元素来增强或升级脚本,也就是说,可以在脚本的每个点上将日志条目添加到单独的.log文件中,并且还可以利用try catch finally块处理异常并将详细的异常消息记录到异常文件之类的东西中。有关更多信息,请检查this和其他有关文件的信息。

另一方面,如果您还不知道,则可以查看是否可以利用this开始停止解决方案来代替自定义脚本。

最后,我建议您使用Az PowerShell代替AzureRM PowerShell,因为根据here的指示,从2018年12月开始,Azure PowerShell Az模块已全面发布,现在是用于与Azure交互的预期PowerShell模块。因此,Az模块是最新推荐使用的模块,而AzureRM模块是较旧的模块。