问题描述
这是脚本:因为我是云基础设施自动化的新手,所以我一直坚持下去。我基本上是在尝试根据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
,则会看到相同的空值表达式错误,如下所示。
因此,要回答有关如何修改此问题的问题,请在我的设置中找到以下更新的脚本。
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
}
}
}
这里脚本的变化是,我们删除了对
的依赖-
$vmstatus.statuses.code
数组(因为不存在的第一个数组元素是您看到空值表达式错误的原因) - split方法
- Get-Culture cmdlet(在这种情况下实际上并不需要使用)
您始终可以通过添加越来越多的错误处理元素来增强或升级脚本,也就是说,可以在脚本的每个点上将日志条目添加到单独的.log文件中,并且还可以利用try catch finally块处理异常并将详细的异常消息记录到异常文件之类的东西中。有关更多信息,请检查this和其他有关文件的信息。
另一方面,如果您还不知道,则可以查看是否可以利用this开始停止解决方案来代替自定义脚本。
最后,我建议您使用Az PowerShell代替AzureRM PowerShell,因为根据here的指示,从2018年12月开始,Azure PowerShell Az模块已全面发布,现在是用于与Azure交互的预期PowerShell模块。因此,Az模块是最新推荐使用的模块,而AzureRM模块是较旧的模块。