How to stop and start Azure VMs in bulk

Starting and stopping Azure VMs in bulk is pretty easy in PowerShell, but you want to filter your VMs based on the correct property. VMs have a Status property that includes StoppedDeallocated, Stopped, RoleReady, etc. If you are attempting to identify VMs based on status, your PowerShell will have to write your script to filter on multiple criteria.

A better option is to use the PowerState property. Your VMs are going to have a PowerState of “Started” or “Stopped”, so turning them on (or off) in bulk based on this property is quite simple. You could take these one-liners into simple Windows scheduled tasks to turn your development and test environments down after quitting time and bring them back online before the team gets into the office the next morning, reducing your Azure spend on non-production compute resources.

Below are a handful of one-liners and a description of the nuances of each.

This first one-liner will shut down every VM in your subscription, but you will be prompted on the last / only VM in a cloud service with an “continuing will result in a new IP address for your deployment” message, and further direction that using the -StayProvisioned parameter will ensure your VM will keep it’s IP address. However, when you use that parameter, the VM remains provisioned, so you also keep getting billed. For test and dev environments, dynamic DNS registration and short time-to-live (TTL) on DNS records should be good enough to allow you to simply shutdown and deallocate to save dollars.

Get-AzureVM |  Where-Object {$_.powerstate -eq ‘Started’} | Stop-AzureVM

If you add the -Force parameter to the end of the one-liner (as shown below), the VMs are stopped and deallocated (meaning you are only being billed for the storage they consume) without the prompt.

Get-AzureVM |  Where-Object {$_.powerstate -eq ‘Started’} | Stop-AzureVM -Force

Replace the -Force parameter with -StayProvisioned as shown below and the annoying prompt is still avoided, but your VMs wind up in with a status of “Stopped” instead of “StoppedDeallocated”. This means the VMs will come back online with the same IP address, but the billing does not stop between power off and the next power on.

Get-AzureVM |  Where-Object {$_.powerstate -eq ‘Started’} | Stop-AzureVM -StayProvisioned

To start the VMs up again, you can simply reverse the flow with a couple of small changes, as shown below.

Get-AzureVM |  Where-Object {$_.powerstate -eq ‘Stopped’} | Start-AzureVM

Naturally, you can add multiple criteria to the Where-Object filtering to filter based on VM name, cloud service name and other properties to shut down specific subsets of your VMs. In a future post we will look at scheduled tasks, time-based actions and moving this process into Azure’s PowerShell Workflow based orchestration engine, Azure Automation.

Leave a Reply