The last week has been a blur because I didn’t sleep. I spent days helping a client restore every single VM that had running in Azure (about 250). Why? They got a ransomware virus and their entire network was trashed.

One of the things that saved them, and me for that manor, was that I’ve had a passion for the Azure CLI for a long time.

Honestly, I’m not much of a programmer. I call myself a recovering IT guy meaning I grew up in the era of SETUP.EXE and nothing was ever scripted. Those days are LONG gone. Over the past few years I’ve dedicated myself to learning how to script and specifically in bash using the Azure CLI for all my tasks.

In this post I’m going to show you a pattern that I used over and over during the outage including some scripts and snips that I wrote on the fly that helped me get them back online.

One thing that you need to understand about the Azure CLI is how the command structure works. All the top-level commands have groups. For example: az vm is the command group for virtual machines.

You can see a list of all the commands and further sub-groups available to you by running the following command:

az vm -h

Output from Azure CLI VM Help Command

If you dedicate yourself to learning these, you will start to build some strong Azure Kung-Fu!

#!/bin/bash ########################################################################################### # Azure CLI Kung-Fu - Blog post # Dan Patrick - @deltadan # #Script Purpose # - stop an azure vm (not deallocate) ########################################################################################### rg=resourceGroupName vm=vmName az vm stop --resource-group $rg \ --name $vm

Doing these one at a time would be crazy! So, I have an array template that I use for commands that can be updated quickly to run the same task in a loop.

This is a great little script to have for running the same command over and over. Here is an example of how you could stop all the VMs in a space separated list you provide as an array. Just paste in a list of VMs into the array, update the variable of the resource group and fire away.

#!/bin/bash ########################################################################################### # Azure CLI Kung-Fu - Blog post # Dan Patrick - @deltadan # #Script Purpose # - stop a list of azure vms listed in the array (not deallocate) ########################################################################################### array=(vm1Name vm2Name) for vms in "${array[@]}" do az vm stop --resource-group $rg \ --name $vms done

Now, for the array above to be useful we need have that list of the VM names. This is my favorite snip that I use everywhere because it’s so powerful: I call it “list-foo”.

The idea of list-foo is to output the names of resources using the “list” command from any group or sub group of az along with the tsv output type. All the commands have “list”, so I can call that and have an output of the resources which we then format using a few bash command line tools sed, tr, cut and rev (this was not easy to figure out) Viola! They are then formatted into this space separated format need to it can be pasted into that array template!

To run list-foo just update the command variable which will call az using a different group command and then the list output will be formatted into a file I can then open and slip into the array script from above.

#!/bin/bash ########################################################################################### # Azure CLI Kung-Fu - Blog post # Dan Patrick - @deltadan # #Script Purpose # - load the output of a az command into a variable named $listFoo # - load the output of a az command into a file in the current directory named list-foo.txt ########################################################################################### rg=resourceGroupName command=vm listFoo=$(az $command list -g $rg --query [].name --output tsv | sed "s/.*/& /" | tr -d '

' | rev | cut -c 2- | rev) az $command list -g $rg --query [].name --output tsv | sed "s/.*/& /" | tr -d '

' | rev | cut -c 2- | rev>>list-foo.txt

Notice that I also have a line that loads the output into the variable listFoo . This allows me to add this line to a script where we load the list and then pass the list into an array.

If you want to run all of this as one command, just put listFoo at the top of the other script and call the output as a variable and pass that into the array value.

#!/bin/bash ########################################################################################### # Azure CLI Kung-Fu - Blog post # Dan Patrick - @deltadan # #Script Purpose # - load the output of a az command into a variable named $listFoo # - load the output of a az command into a file in the current directory named list-foo.txt # - stop all azure vms found from by listFoo (not deallocate) ########################################################################################### #Load variables rg=resourceGroupName command=vm #Load listFoo and create output file listFoo=$(az $command list -g $rg --query [].name --output tsv | sed "s/.*/& /" | tr -d '

' | rev | cut -c 2- | rev) az $command list -g $rg --query [].name --output tsv | sed "s/.*/& /" | tr -d '

' | rev | cut -c 2- | rev>>list-foo.txt #Pass listFoo to the command and execute loop array=($listFoo) for vms in "${array[@]}" do az vm stop --resource-group $rg \ --name $vms done

And with that, you have the basis for your Kung Fu. Using this technique, you can write some pretty awesome scripts in no time.

In the case of my client last week, well we saved them $3.2 million dollars…

Happy scripting young grasshopper!

Sample scripts here: https://github.com/deltadan/az-cli-kung-fu

PS: there is a bonus list-foo sample that allows you to do a query to load the variables!

Article Author

Dan Patrick Dan Patrick is the Chief Infrastructure Architect for Solliance and a 15 year veteran at Microsoft. He has an extensive background in IT Infrastructure and Operations. Dan has both architected and lead teams building and supporting some of the largest service providers in North America with as many 15,000 Windows Servers and 120 million endpoints. Dan has worked with Azure IaaS solutions extensively since 2012. He has a passion for Virtualization with deep experience leveraging Hyper-V, Vmware, and Citrix. He is also a Clustering specialist focusing on large host clusters and SQL Always On Availability Groups. Recently Dan, authored the Networking, Azure Active Directory and Containers portion of the 70-533 Exam Reference for Microsoft Press. You can follow him on Twitter @deltadan