2017-03-07 83 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