Как использовать 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}
Определенно, есть и другие способы сделать это, но такой подход всегда работал для меня