
Getty Images/iStockphoto
PowerShell while loop tips for infrastructure automation
Loops enhance task automation scripts by enforcing conditions before the script progresses. This tutorial explains the concepts and offers tips for avoiding an endless loop.
PowerShell has all the looping capabilities you expect from a programming language, but one particular type has added value for admins concerned with infrastructure management and monitoring.
Automating repetitive tasks is an essential skill of efficient systems administration. In the course of writing an automation script, an admin will most likely use a loop when a script needs to wait for a particular condition or execute a task until a specific condition is met. Of the several types of loops available in PowerShell, the while loop is especially useful because it can wait for an infrastructure deployment sequence to finish or it can monitor services and, by doing so, reduce the manual workload of the admin. This tutorial explains the loops available in PowerShell, how to use these loops in Microsoft environments and how to fix scripts with loops when things don't work as expected.
What are the types of loops used in PowerShell?
Before diving into how while loops work in PowerShell, it's important to understand when to use each of the loops:
- For loop. The for loop is ideal for executing a block of code a particular number of times specified using a counter variable.
- Foreach loop. The foreach loop iterates through an array and executes some code for each item in that array.
- While loop. An expression continually executes a section of code while a condition evaluates to true. If the condition is not true on the first check, then the code never runs.
- Do-while loop. The do-while loop is similar to the while loop, except the code section executes and then the script evaluates the condition. The code runs at least once, regardless of the condition.
- Do-until loop. Similar to the do-while loop, the code runs at least once, regardless of the condition. After the expression executes, the condition is evaluated. Once the condition is true, the loop stops.
What are scenarios for using PowerShell while loops?
All the different loops in PowerShell are handy for specific circumstances. The while loop is especially useful when you need to repeatedly run some code until the condition is met. Unlike a for loop or a foreach loop, the code does not need to set the number of iterations.
Some basic, high-level examples of using a while loop are the following:
- Waiting for some event to happen.
- Iterating through a section of code without a set number.
Specific examples are the following:
- Infrastructure provisioning. Waiting for infrastructure to provision before continuing.
- Service monitoring. Waiting for something to start or stop before executing some code.
- Status monitoring. Checking the status of a resource until it meets a specific condition before executing some code.
- Input validation. Continually asking for input until it meets a specific condition.
What is the basic syntax of a PowerShell while loop?
A while loop has simple syntax compared to other loops. The following code shows the basic syntax of a while loop in PowerShell.
while ('<condition>') {
'<code>'
}
To populate that template with a basic example, it might look like the following code that performs an example of a simple counter.
$x = 0
while ($x -lt 10) {
$x++
}
$x
Here's what happens in the code sample:
- $x is set to 0.
- The while loop condition is evaluated and returns $true since 0 is less than 10.
- $x is incremented ($x++), which brings it to 1.
- Repeat steps 2 and 3 until $x becomes 10.
- The while loop condition is evaluated and returns $false since $x -- now 10 -- is no longer less than 10.
- The code in the while loop is skipped, and the final line is executed.
Execute infrastructure provisioning using a while loop
Let's say that you are working on a script to deploy some infrastructure to Azure and you want the script to wait until the deployment completes. The while loop in the following PowerShell code waits until the resource exists before continuing the script.
New-AzContainerGroup @splat
while ((Get-AzContainerGroup -ResourceGroupName $splat.ResourceGroupName | Where-Object{$_.Name -eq $splat.Name}).Count -eq 0) {
Start-Sleep -Seconds 10
}
# Code to execute after infra is deployed
In this script, here's what happens:
- A cmdlet creates the Azure container instance.
- The while loop condition checks for the container instance.
- The script checks for a container instance with the name the code created and returns $true if the instance is not found.
- If the while loop condition returns $true, the script sleeps for 10 seconds.
- If the while loop condition returns $false, then the code after the while loop is executed.
Perform infrastructure monitoring with a while loop
Another good scenario to use a while loop in PowerShell is monitoring. For example, the following snippet in your script checks for a service to start.
while ((Get-Service 'serviceName').Status -ne 'Running') {
Start-Sleep -Seconds 5
}
In this section of code, the while loop continually loops until the status of the service is Running.
To check if a service stops and then send an alert, the code could set the condition to check for it to be running.
while ((Get-Service 'serviceName').Status -eq 'Running') {
Start-Sleep -Seconds 5
}
Send-MailMessage @splat
The while loop continually loops until the status of the service is not Running.
How to troubleshoot while loops
It's difficult to correct errors in while loops when they don't behave as expected. Since they don't have a predetermined number of executions, it's possible to create a while loop that never stops looping.
To prevent infinite loops, ensure the while loop condition eventually returns $false. This sounds simple, but it may require some additional testing. A good way to debug a while loop is to add some Write-Host or Write-Output statements that include details about the values being evaluated in the condition statement. For example, the container instance deployment example could add a line to output the current container instances.
New-AzContainerGroup @splat
while ((Get-AzContainerGroup -ResourceGroupName $splat.ResourceGroupName | Where-Object{$_.Name -eq $splat.Name}).Count -eq 0) {
Write-Host "Container instances: $((Get-AzContainerGroup -ResourceGroupName $splat.ResourceGroupName).Name -join ', ')"
Start-Sleep -Seconds 10
}
Another way to limit the chance of an infinite loop in a while loop is to implement a maximum number of loops in the script. For example, after deploying a resource to Azure, it is reasonable to assume the resources should be deployed within a few minutes. Add a counter variable, and limit its maximum value to 120 in the script.
$counter = 0
New-AzContainerGroup @splat
while ((Get-AzContainerGroup -ResourceGroupName $splat.ResourceGroupName | Where-Object{$_.Name -eq $splat.Name}).Count -eq 0) {
$counter++
if ($counter -ge 120) {
Throw 'Deployment has taken longer than 20 minutes.'
}
Start-Sleep -Seconds 10
}
# Code to execute after infra is deployed
The example uses an if statement inside the while loop instead of including it in the condition to show the script exits due to $counter being greater than 120. Using Throw halts the script at that point rather than continuing.
Another way to use a counter in a while loop is to write some output periodically. For example, in the service monitoring script, a counter and an if statement can be used to periodically write to a log file to let the admin know the script is still running.
$counter = 0
while ((Get-Service 'serviceName').Status -eq 'Running') {
$counter++
if ($counter % 60 -eq 0) {
'serviceName is still running...' | Out-file $logPath -Append
}
Start-Sleep -Seconds 5
}
Send-MailMessage @splat
The script uses the modulus operator (%) to check if the counter is divisible by 60. If so, then the script writes a log entry. The output occurs every 60 iterations, which is slightly longer than every five minutes.
Anthony Howell is an IT strategist with extensive experience in infrastructure and automation technologies. His expertise includes PowerShell, DevOps, cloud computing, and working in both Windows and Linux environments.