Dec 14

PowerCLI Script to Shutdown My Home Lab

Ran across a PowerCLI script that can be used to shutdown your virtual infrastructure written by Alan Renouf and thought it would be pretty handy to use to automate shutting down my home lab.

The original script attempts to shutdown VMs “cleanly” using Shutdown-VMGuest. Shutdown-VMGuest attempts to shutdown the VMs OS and requires that VM Tools be installed and running. Most of the VMs in my lab are running Damn Small Linux (DSL) and do not have VM tools installed so this would not work and it would shutdown the host without shutting down the VMs first. Not really a big deal but I wanted to make the process just a bit cleaner.

I changed the script to first shutdown VMs that are powered on and have VM tools running. It then waits $waittime in seconds and uses Stop-VM to forcefully power off any remaining powered on VMs. As in the original script it then waits $waittime or until no VMs are powered on to shutdown the ESXi hosts.

Connect-VIServer MyVIServer

# Set the amount of time to wait before assuming the remaining powered on guests are stuck
$waittime = 60 #Seconds

# Get All the ESX Hosts
$ESXSRV = Get-VMHost

# For each of the powered on VMs with running VM Tools
Foreach ($VM in ($ESXSRV | Get-VM | Where {$_.PowerState -eq "poweredOn" -and $_.Guest.State -eq "Running"})){
    # Shutdown Guest
    write-host "Shutting down $VM"
    $VM | Shutdown-VMGuest -Confirm:$false

Write-host "Pausing for $waittime seconds to allow VMs to shutdown cleanly"
sleep $waittime

#Force Poweroff of any VMs still running
Foreach ($VM in ($ESXSRV | Get-VM | Where {$_.PowerState -eq "poweredOn"})){
      # Power off Guest 
      write-host "Powering off $VM"
      $VM | Stop-VM -Confirm:$false

$Time = (Get-Date).TimeofDay
do {
    # Wait for the VMs to poweroff
    sleep 1.0
    $timeleft = $waittime - ($Newtime.seconds)
    $numvms = ($ESXSRV | Get-VM | Where { $_.PowerState -eq "poweredOn" }).Count
    Write-host "Waiting for shutdown of $numvms VMs or until $timeleft seconds"
    $Newtime = (Get-Date).TimeofDay - $Time
    } until ((@($ESXSRV | Get-VM | Where { $_.PowerState -eq "poweredOn" }).Count) -eq 0 -or ($Newtime).Seconds -ge $waittime)

# Shutdown the ESX Hosts
Write-host "Shutting down hosts"
$ESXSRV | Foreach {Get-View $_.ID} | Foreach {$_.ShutdownHost_Task($TRUE)}

Write-Host "Shutdown Complete"

To use the script just change MyVIServer in line 1 to be the IP address or hostname of you vCenter server. Set $waittime at line 4 to be the number of seconds to wait before forcefully powering off VMs. The $waittime may need to be increased depending on the speed of your lab and the number of VMs that are shutting down. Run the script as you would any other PowerCLI script.

It is probably not completely necessary to force the shutdown of all VMs before shutting down the hosts. They will be shutdown when the host they are running on is shutdown. It just gave me some PowerCLI practice and it works.

Be EXTREMELY careful with this script. When you run it all VMs and Host managed by the vCenter you are connecting to will be shutdown!


Thanks again to Alan Renouf for the original script which can be found at http://www.virtu-al.net/2010/01/06/powercli-shutdown-your-virtual-infrastructure/.

If you found this script useful or have other ideas for improvements post to the comments.

About the author


Hersey Cartwright is an IT professional with extensive experience designing, implementing, managing, and supporting technologies that improve business processes. Hersey is Solutions Architect for SimpliVity covering Virginia, Washington DC, and Maryland. He holds the VMware Certified Design Expert (VCDX-DV #128) certification. Hersey actively participates in the VMware community and was awarded the VMware vExpert title in 2016, 2015, 2014, 2013, and 2012. He enjoys working with, teaching, and writing about virtualization and other data center technologies. Follow Hersey on Twitter @herseyc


Skip to comment form

  1. PJ Bryant

    Does this script not make the assumption that the VC is not running on the server farm. If it were, as soon as you shutdown the guest VM, you end up with no connection to do the rest of the script?

    1. vHersey


      You are correct the script does assume that the VC is not a VM running on the environment you are shutting down. If your VC is running on one of the ESXi servers you would need to modify the script a bit to determine which host the VC is on and leave that host and VM running. Once the other VMs and hosts are should down you could then connect directly to the host and shutdown the VC VM and then the host.


  2. Thomas

    I was looking for acript to shut down all the guest machines and then the esxi 5.1 host. I am new to scripting , it would be great if somebody can help me out in how to execute this script.

    I tried saving it as a .ps1 file and run , didnt work.
    I tried pasting the contents of the script to the vmware power cli and received an error “current licence or ESXi version prohibits execution of the requested operation”

  3. Josh Atwell

    Great Post Hersey
    PowerCLI can not run against the free version of ESXi. Unfortunately remote management tools are not supported on the free version. That is why you’re getting that error.

    In the event that you have vCenter running in the same cluster you could always put in a filter before the main filter.
    Get-VM | Where{$_.Name -ne “”} | Where {$_.PowerState……. }

    You could then change the count listed in line 34 to be 1 so that the vCenter is the last one.

    You could store the ESXi host list in an object and do individual connections to those to initiate their shutdown so you’re not dependent on vCenter. Definitely an interesting conundrum, especially for a homelab. Hope this provides some suggestions for providing the functionality you mentioned.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

three × 1 =