locked
Powershell Script to Shut Down Servers RRS feed

  • 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'}


    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 $comp

    Accomplishes 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
    Friday, December 12, 2014 6:41 AM