Answered by:
Powershell Script to Shut Down Servers

Question
-
Hi All
Im busy writing a Powershell script that shutdown VM that are running on Hyper V. But the condition that I have is that the script needs to loop through the VM that are running shutdown 1 and waits for a 1 minute and on to the next one. At the moment that is my challenge to loop through the VM. Can anyone help or has a script that I can work on.
- Moved by Bill_Stewart Monday, May 18, 2015 4:52 PM Abandoned
Thursday, December 11, 2014 9:52 AM
Answers
-
It's pretty much the same. Here's an example.
$servers = @('server1', 'server2', 'server3')
ForEach ($server in $servers)
{
$VM = Get-VM -ComputerName $server
$VMR = $VM | Where-Object -FilterScript {
$_.State -eq 'Running'
}
ForEach ($Machine in $VMR)
{
Stop-VM $Machine
Start-Sleep -Seconds 60
}Stop-Computer -ComputerName $server -Force
}
- Edited by _TimPringle Thursday, December 11, 2014 11:59 AM
- Proposed as answer by _TimPringle Thursday, December 11, 2014 12:29 PM
- Marked as answer by Just Karl Friday, May 29, 2015 9:20 PM
Thursday, December 11, 2014 11:58 AM
All replies
-
You can use Get-VM and Stop VM to perform the actions.
(See example 2) http://technet.microsoft.com/en-us/library/hh848479.aspx
http://technet.microsoft.com/en-us/library/hh848468.aspx
Also, the Start-Sleep cmdlet: http://technet.microsoft.com/en-us/library/ee177002.aspx
You can use the Get-VM to find your VMs then pass those into a foreach loop which would stop each one then wait for 1 minute before processing the next.
Thursday, December 11, 2014 10:57 AM -
Hi Alex
Im done with that part but I need a foreach loop that will set the condition to loop through the VM and shut them down per minute and end up shutting down the host.
$VM = Get-VM -ComputerName Server1
$VMR = $VM | Where-Object {$_.State -eq 'Running'}- Edited by Lebza Powershell Scripting Thursday, December 11, 2014 11:12 AM
Thursday, December 11, 2014 11:04 AM -
Can you try something like this :
$VM = Get-VM -ComputerName Server1
$VMR = $VM | Where-Object -FilterScript {
$_.State -eq 'Running'
}
ForEach ($Machine in $VMR)
{
Stop-VM $Machine
Start-Sleep -Seconds 60
}
Stop-Computer -ComputerName Server1 -Force
Thursday, December 11, 2014 11:22 AM -
Thanks a lot Tim so what happens if I've got multiple VM Host and I would like to run the script on all the VM host.Thursday, December 11, 2014 11:46 AM
-
It's pretty much the same. Here's an example.
$servers = @('server1', 'server2', 'server3')
ForEach ($server in $servers)
{
$VM = Get-VM -ComputerName $server
$VMR = $VM | Where-Object -FilterScript {
$_.State -eq 'Running'
}
ForEach ($Machine in $VMR)
{
Stop-VM $Machine
Start-Sleep -Seconds 60
}Stop-Computer -ComputerName $server -Force
}
- Edited by _TimPringle Thursday, December 11, 2014 11:59 AM
- Proposed as answer by _TimPringle Thursday, December 11, 2014 12:29 PM
- Marked as answer by Just Karl Friday, May 29, 2015 9:20 PM
Thursday, December 11, 2014 11:58 AM -
Thanks a million Tim worked.Thursday, December 11, 2014 12:24 PM
-
Glad it worked mate.Thursday, December 11, 2014 12:29 PM
-
That looks ok, but you can make it a bit cleaner, the filter command is a bit dated now:
$servers = @('server1', 'server2', 'server3') ForEach ($server in $servers) { $VMs = Get-VM -ComputerName $server| Where-Object {$_.State –eq 'Running'} ForEach ($Machine in $VMs) { Stop-VM $Machine Start-Sleep -Seconds 60 } Stop-Computer -ComputerName $server -Force }
A further improvement would be to run each one of the servers in parallel or remotely execute the code on the servers themselves. For one or two servers it doesn't make a huge difference but if you've got 10 servers each with 4 VMs then you're looking at a run time of 40 minutes instead of a run time of 4.Thursday, December 11, 2014 1:23 PM -
Get-Vm -computer $comp | Stop-Vm
Stop-Computer $compAccomplishes the same thing as Stop-Vm does nothing on a stopped VM and the pipeline waits until the machine is stopped before moving on.
THere is no need to be more complicated then that.
If you have a lot of VM then the shutdown can take a long time doding it this way. Using a parrallel workflow would be much faster.
¯\_(ツ)_/¯
Thursday, December 11, 2014 1:33 PM -
That looks ok, but you can make it a bit cleaner, the filter command is a bit dated now:
$servers = @('server1', 'server2', 'server3') ForEach ($server in $servers) { $VMs = Get-VM -ComputerName $server| Where-Object {$_.State –eq 'Running'} ForEach ($Machine in $VMs) { Stop-VM $Machine Start-Sleep -Seconds 60 } Stop-Computer -ComputerName $server -Force }
A further improvement would be to run each one of the servers in parallel or remotely execute the code on the servers themselves. For one or two servers it doesn't make a huge difference but if you've got 10 servers each with 4 VMs then you're looking at a run time of 40 minutes instead of a run time of 4.Bit dated? Disagree on that one.
-FilterScript is what Where-Object actually uses when you omit the parameter name.
Best practices state that full parameters should be used for commands, which is what that is.
Thursday, December 11, 2014 1:45 PM -
Hi Everyone
Just a quick question if want to convert the script to start up the the VM Host plus the VM's is the below correct.
$servers = @('server1', 'server2', 'server3')
ForEach ($server in $servers)
{
$VMs = Get-VM -ComputerName $server| Where-Object {$_.State –eq 'Off'}
ForEach ($Machine in $VMs)
{
Start-VM $Machine
Start-Sleep -Seconds 60
}
Start-Computer -ComputerName $server -Force- Marked as answer by Lebza Powershell Scripting Thursday, December 18, 2014 2:46 PM
- Unmarked as answer by Bill_Stewart Monday, May 18, 2015 4:51 PM
Friday, December 12, 2014 6:41 AM