Как использовать powershell для ожидания завершения действия

У меня есть скрипт для запуска виртуальных машин / остановки их в определенное время. Проблема в том, что я хочу, чтобы скрипт завершал работу только тогда, когда все виртуальные машины запущены / работают или когда они освобождены / остановлены. Моя текущая проблема - когда виртуальная машина запускается, она ждет, пока не запустится, прежде чем перейти к следующей.

Например: vm1 запускается.. vm2 запускается.. vm3 запускается..

vm1 is now running..
vm2 is still starting
vm3 is still starting

vm1 is now running..
vm2 is now running..
vm3 is now running..

Затем скрипт выходит.

Полный сценарий здесь

$ACTION="старт"

Write-Output "Number of Virtual Machines: $($GetVMS.Name.Count)" `n
$GetVMS | Format-Table

$startstopvm = {

$ResourceGroupName = $args[0]
$Name =  $args[1]
$ACTION = $args[2]

# Get VM status
try {
    $VMs = Get-AzureRmVM -Name $Name -ResourceGroupName $ResourceGroupName -Status -WarningAction SilentlyContinue
} catch {
    Write-Output ("Cloud not get vm $Name in $ResourceGroupName")
    $Error[0]
    Exit 1 
}

if ($ACTION -eq "start")
{
    foreach ($VM in $VMs)
    {
        if ($VM.Statuses[1].Code -eq "PowerState/running")
        {
            Write-Output ($VM.Name + " in " + $VM.ResourceGroupName + " is already running")
        }
        else
        {
            # The VM needs to be started
            Write-Output ("Starting VM " + $VM.Name)
            $startVM += Start-AzureRmVM -Name $VM.Name -ResourceGroupName $VM.ResourceGroupName -AsJob -ErrorAction Continue

            $startTime = Get-Date

            $timeElapsed = $((Get-Date) - $startTime).TotalMinutes

            while ($timeElapsed -lt 2) 
            {
                $startVM = Get-AzureRmVM -Name $VM.Name -ResourceGroupName $VM.ResourceGroupName -Status -WarningAction SilentlyContinue

                if ($startVM.Statuses[1].Code -match "PowerState/(running|starting)")
                {
                    # The VM started, so send notice
                    Write-Output ($VM.Name + " in " + $VM.ResourceGroupName + " has been started`n")
                    break
                }
                Start-Sleep -s 30
            }

            if ($getStat.Statuses[1].Code -ne "PowerState/(running|starting)")
            {
                # The VM failed to start, so send notice
                Write-Output ($VM.Name + " failed to start`n")  
            }
        }
    }
}

ПРИМЕЧАНИЕ: я читаю имя виртуальной машины и RG из файла

try {
    $VMList = Get-Content C:\Users\local\Desktop\VMs.csv | ConvertFrom-Csv
} catch {
    Write-Output ("Cannot open file...")
    exit -1
}

$Result = @()

foreach ($vm in $VMList) {
    Invoke-Command -ArgumentList $vm.ResourceGroupName, $vm.Name, $ACTION -Verbose -ScriptBlock $startstopvm
}

1 ответ

Простейший способ сделать это в прошлом - использовать -Wait параметр на Start-Process Командлет.

Вы должны быть в состоянии реализовать это с небольшими изменениями.

Сохранение текущего блока кода в отдельный .ps1 т.е. startstopvm.ps1

Вы могли бы затем изменить Invoke-Commmand строка, чтобы прочитать что-то вроде:
Invoke-Command -ArgumentList $vm.ResourceGroupName, $vm.Name, $ACTION -Verbose -ScriptBlock {Start-Process powershell.exe -Argument "C:\Scripts\Backup.ps1 TestBackup" -Wait}

Определенно, есть и другие способы сделать это, но такой подход всегда работал для меня

Другие вопросы по тегам