PowerShell Operational runbooks
A runbook is a procedure someone can follow at three in the morning without knowing what you know. Written well, it is also the thing you automate from.
Documentation: Microsoft Learn
Overview
The structure that works has five parts. What triggers it, so nobody runs it speculatively. Pre-checks that confirm the situation matches, because the same alert has more than one cause. The action, with a dry run first where that is possible. Verification that the fix worked, which is different from the action having completed. And an escalation path with a condition, so nobody has to decide alone whether this is now someone else's problem.
The verification step is the one most often left out. Restarting a service succeeds; the service being healthy afterwards is a separate fact. A runbook that stops at the action tells you the button was pressed, not that the problem is gone.
Write commands out in full, with real parameter names. A runbook that says check the service assumes the reader knows how, which defeats the purpose.
Escalation needs a condition, not a suggestion. Twice in an hour is actionable; if it keeps happening is not.
When the same runbook has been followed a few times without judgement being needed, that is the signal to automate it. Runbooks that still need judgement should stay manual, and saying so is part of writing a good one.
Inspect this example’s structure
Read the command and its supplied arguments. This example requires real PowerShell or its module; this diagram does not execute it.
$runbook = [pscustomobject]@{
Name = 'Restart failed print spooler'
Trigger = 'monitoring alert PRN-001'
Precheck = 'Get-Service Spooler; Get-WinEvent -FilterHashtable @{LogName="System";Id=7031}'
Action = 'Restart-Service Spooler -WhatIf, then without -WhatIf'
Verify = 'Get-Service Spooler | Where-Object Status -eq Running'
Escalate = 'if it fails twice in an hour, raise to platform team'
}
$runbook | Format-List- Stage 1$runbook
Positional values or no named parameters - Stage 2Format-List
Positional values or no named parameters
An example to inspect
Preview the example. Sign in for the full lesson and activities.
$runbook = [pscustomobject]@{
Name = 'Restart failed print spooler'
Trigger = 'monitoring alert PRN-001'
Precheck = 'Get-Service Spooler; Get-WinEvent -FilterHashtable @{LogName="System";Id=7031}'
Action = 'Restart-Service Spooler -WhatIf, then without -WhatIf'
Verify = 'Get-Service Spooler | Where-Object Status -eq Running'
Escalate = 'if it fails twice in an hour, raise to platform team'
}
$runbook | Format-ListWhat happens
This prints one runbook as a list. Precheck includes both the service state and the specific event id, because the alert alone does not tell you which failure this is. Action shows -WhatIf before the real run. Verify is separate from Action deliberately. Escalate carries a numeric condition rather than a judgement call.
Worth remembering
- Five parts: trigger, pre-checks, action, verification, escalation.
- Verification is separate from the action succeeding.
- Write commands in full; do not assume the reader knows the cmdlet.
- Escalation needs a measurable condition.
Primary documentation
Where-Object reference · Get-Service reference · Restart-Service reference
Try it
Illustrative output · values vary by environment
Example reader
Inspect this page's example
Run supported commands against the practice data, or inspect the example without executing it.
Ready to inspect.
Prints a complete runbook with all five sections.
Show reference output
Illustrative output · values vary by environment
Name : Restart failed print spooler
Trigger : monitoring alert PRN-001
Precheck : Get-Service Spooler; Get-WinEvent -FilterHashtable @{LogName="System";Id=7031}
Action : Restart-Service Spooler -WhatIf, then without -WhatIf
Verify : Get-Service Spooler | Where-Object Status -eq Running
Escalate : if it fails twice in an hour, raise to platform teamPractise this
Export an incident report
Export Id, LevelDisplayName and Message for Error events to C:\Lab\report.csv.
The sandbox is visible now. Sign in with Google only when you run or check a task; commands and temporary files are discarded when you leave.
Run a command to inspect its result.