2017-03-07 116 views
2

這裏是場景 - 我通過Powershell/PowerCLI(VMwares Powershell模塊)遠程啓動虛擬機,一旦虛擬機啓動,我將針對虛擬機運行一系列cmdlet。Powershell/PowerCLI循環,超時和退出

目前我有這段代碼:

Start-VM "my VM Name" -runAsync 
$vm = Get-VM | where { $_.name -eq "my VM Name" }  

start-sleep -seconds 20 
do { 
    start-sleep -seconds 5 
    $toolsStatus = ($VM | Get-View).Guest.ToolsStatus 
} until ($toolsStatus -eq 'toolsOK') 

其中一期工程 - 虛擬機啓動循環將檢查,直到VMware Tools是爲VMware(這意味着虛擬機完全啓動進入OS)報告中。

但是,這會無限期地運行,所以在虛擬機無法成功引導的情況下 - 腳本掛起。所以,我試圖在計時器添加它是否運行了5分鐘過去了退出腳本:

Start-VM "My VM Name" -runAsync 
$VM = Get-VM | where { $_.name -eq "My VM Name" } 

$timeout = new-timespan -minutes 5 
start-sleep -seconds 5 
$toolsStatus = ($VM | Get-View).Guest.ToolsStatus 
$sw = [diagnostics.stopwatch]::StartNew() 
while ($sw.elapsed -lt $timeout) { 
    if ($toolsStatus -eq 'toolsOK') { 
     return 
    } 
    start-sleep -seconds 5 
} 
Exit 

成功地退出5分鐘後腳本。這個問題是,當我測試這個 - 虛擬機已啓動,我得到一個響應,表明VMtools已迴應,但循環不停止。它會一直持續到超時退出,而不是進入下一步。

我沒有使用過這種類型的循環,因此我會確定我很接近 - 但我錯過了一些東西。

回答

0

你並沒有更新你的循環中的$toolsStatus,因此即使VM已經啓動,它也不會退出。只需移動循環內的檢查。

Start-VM "My VM Name" -runAsync 
$VM = Get-VM | where { $_.name -eq "My VM Name" } 

$timeout = new-timespan -minutes 5 
start-sleep -seconds 5 
$sw = [diagnostics.stopwatch]::StartNew() 
while ($sw.elapsed -lt $timeout) { 
    $toolsStatus = ($VM | Get-View).Guest.ToolsStatus 
    if ($toolsStatus -eq 'toolsOK') { 
     return 
    } 
    start-sleep -seconds 5 
} 
Exit 
+0

啊!我以爲我錯過了一些東西 - 修復了我的循環! – TheDemonLord

1

應該只是一個簡單的邏輯修復。在最終while循環,增加與-and兩個表達式和否定$toolStatus

while ($sw.elapsed -lt $timeout -and $toolsStatus -ne 'toolsOK'){ 
    start-sleep -seconds 5 
} 

當一個人變成假,則循環將結束。

1

VMWare已經有一個等待的命令。

Start-VM "My VM Name" -runAsync 
$VM = Get-VM | where { $_.name -eq "My VM Name" } | Wait-Tools -TimeoutSeconds 180 

https://www.vmware.com/support/developer/PowerCLI/PowerCLI41U1/html/Wait-Tools.html

我讀過有關運行VMTools和OS沒有被啓動的問題。只要Windows徽標出現VMTools似乎報告爲正在運行,這可能會導致問題。我更喜歡使用Powershell命令來ping機器,直到得到響應。

$thisisaddress = (Get-NetIPAddress | where {$_.AddressFamily -eq "IPv4" -and $_.InterfaceAlias -eq "Ethernet"}).ipaddress 

$pingMachine = New-Object System.Net.NetworkInformation.Ping 

$timeout = new-timespan -Minutes 1 
$sw = [diagnostics.stopwatch]::StartNew() 
while ($sw.elapsed -lt $timeout -and $pingStatus.Status -ne 'Success'){ 
    $pingStatus = $pingMachine.Send($thisisaddress) 
    $pingStatus 
} 
+0

我沒有意識到存在!對於這個問題 - 我已經實施了你的解決方案,因爲它更加優雅和優雅。然而,我已經標記了另一個答案,因爲它解決了我原始腳本中的語法/邏輯錯誤(我認爲這對其他人在處理超時循環時更有幫助) – TheDemonLord

+0

您對虛擬機的搜索速度很慢。抱歉它看起來很差。試試這些Measure-Command {Get-VM |其中{$ _名-eq 「yourvmname」。}} TotalSeconds:18.5221952 措施命令{GET-VM -name yourvmname} TotalSeconds:6.229672 措施命令{獲取視圖-viewtype的虛型濾波器@ {「name」=「yourvmname」}} TotalSeconds:1。2584678 Measure-Command {Get-view -viewtype VirtualMachine -property name -filter @ {「name」=「yourvmname」}} TotalSeconds:1.2559065 – user3520245