UPDATED – Nov 2023 – Minor correction in the script

Over the last couple of years we have been playing with several different scripts to create Snapshots of virtual machines (VM) in Azure and none of them have had us completely happy.

Our most recent Azure Snapshot script from about a year ago, did work and was easy to understand and modify but it shut down/reboot each of the virtual machines one by one which meant:

  1. we weren’t able to take the snapshots in advance of our outage window
  2. wait for each machine to be snapped serially, rather than in parallel meant it took a lot of time

As a result we spent more time today working on it and came up with this excellent script that does not shut down the virtual machines but does create snapshots in parallel so it is way faster

To use this all you have to do is change the name of the resource group(s) which we have marked in bold so they are easy for you to spot. And yes, this script will back up any virtual machine to a snapshot, including Windows and Linux machines. And, yes again there is a difference between a snapshot and a backup, and if you were not aware of that you should read THIS.

# Get a list of all resource groups 
$resource_groups = (az group list --query '[].name' --output tsv) -split "`n" 

# Loop through each resource group 
foreach ($resource_group in $resource_groups) { 
    Write-Host "Processing resource group: $resource_group" 

    # Get a list of all virtual machines STARTING with the prefix in the resource group 
	$vms = (az vm list --resource-group $resource_group --query "[? !contains(name, 'YOUR-RG-NAME-HERE')].[name]" --output tsv) -split "`n"

    # Loop through each virtual machine and create a snapshot of its managed disk 
    foreach ($vm in $vms) { 
        Write-Host "Creating snapshot of VM: $vm" 
        $disk_name = (az vm show -d -g $resource_group -n $vm --query "storageProfile.osDisk.name" -o tsv) -split "`n" 
        $snapshot_name = "URTech-SNAP-$vm-$(Get-Date -Format 'yyyyMMddHHmmss')" 
        az snapshot create --resource-group $resource_group --source $disk_name --name $snapshot_name 

Here are three examples of alternate PowerShell commands to take snapshots in Azure that you can sub into the script above replacing the $VMS =… line:

# Use if you want to take snaps of all the machines in YOUR-RG-NAME-HERE and YOUR-SECOND-RG-NAME-HERE
	$vms = (az vm list --resource-group $resource_group --query "[? starts_with(name, 'YOUR-RG-NAME-HERE') && starts_with(name, 'YOUR-SECOND-RG-NAME-HERE')].[name]" --output tsv) -split "`n"


# Use if you want to take snaps of all the machines EXCEPT YOUR-RG-NAME-HERE
	$vms = (az vm list --resource-group $resource_group --query "[? !contains(name, 'YOUR-RG-NAME-HERE')].[name]" --output tsv) -split "`n"


# Use if you want to take snaps of all the machines in YOUR-RG-NAME-HERE but NOT the YOUR-SECOND-RG-NAME-HERE Resource Group (note the ! before starts_with)
	$vms = (az vm list --resource-group $resource_group --query "[? starts_with(name, 'YOUR-RG-NAME-HERE') && !starts_with(name, 'YOUR-SECOND-RG-NAME-HERE')].[name]" --output tsv) -split "`n"

Easiest Way To Run PowerShell Scripts in Azure

how to use an Azure Cloud Shell

There are a number of ways to run Powershell scripts in Azure including uploading the .PS1 files, but as you can see in the screenshot above, all we do here is click the Azure Cloud Shell icon (in the top menu bar of all Azure pages), and then paste the script in.

Note that while the screenshot shows we are in Azure Snapshots when we ran the Powershell script, it doesn’t make any difference. We could have been on ANY page in Azure.

PowerShell Script to Delete All Snapshots

This simple command will delete all snapshots in Azure

Get-AzSnapshot | Remove-AzSnapshot -Force

We hope you find this script useful because we sure as heck did and it took us more than a bit of fiddling to make it work.


Leave a Reply

Avatar placeholder

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