可创建新的 Runbook,或从文件或 Runbook 库中导入现有 Runbook,将 Runbook 添加到 Azure 自动化中。 本文提供有关管理运行手册以及运行手册设计的推荐模式和最佳做法的信息。 可在 Azure 自动化的 Runbook 和模块库中获取有关如何访问社区 Runbook 和模块的全部详细信息。
创建操作手册
使用 Azure 门户或 PowerShell 在 Azure 自动化中创建新的 Runbook。 创建 Runbook 后,即可根据以下信息对其进行编辑:
- 在 Azure 自动化中编辑文本 Runbook
- 了解用于自动化运行手册的 PowerShell 工作流关键概念
- 在 Azure 自动化中管理 Python 2 包
- 在 Azure 自动化中管理 Python 3 程序包(预览版)
在 Azure 门户中创建运行手册
- 登录 Azure 门户。
- 搜索并选择自动化账户。
- 在“自动化帐户”页上,从列表中选择你的自动化帐户。
- 在自动化帐户中,选择流程自动化下的运行簿以打开运行簿列表。
- 单击“创建运行手册”。
- 为运行手册命名。
- 从“Runbook 类型”下拉列表中。 选择其类型。 运行手册名称必须以字母开头,且可包含字母、数字、下划线和连字符
- 选择“运行时版本”
- 输入适用的说明
- 单击创建以创建运行手册。
使用 PowerShell 创建运行簿
使用 New-AzAutomationRunbook cmdlet 命令创建空白运行手册。 使用 Type 参数指定为 New-AzAutomationRunbook 定义的某一种运行手册类型。
以下示例演示了如何新建空白 Runbook。
$params = @{
AutomationAccountName = 'MyAutomationAccount'
Name = 'NewRunbook'
ResourceGroupName = 'MyResourceGroup'
Type = 'PowerShell'
}
New-AzAutomationRunbook @params
导入运行手册
你可以导入 PowerShell 或 PowerShell 工作流 (.ps1) 脚本、图形 Runbook (.graphrunbook) 或者 Python 2 或 Python 3 脚本 (.py) 来创建自己的 Runbook 。 指定导入期间创建的 运行手册类型,同时考虑以下注意事项。
可以将不包含工作流的 .ps1 文件导入到 PowerShell Runbook 或 PowerShell 工作流 Runbook 中。 如果将其导入 PowerShell 工作流 Runbook,它会被转换为工作流。 在这种情况下,会在运行手册中加入注释,以说明所做的更改。
只能将包含 PowerShell 工作流的 .ps1 文件导入到 PowerShell Workflow runbook 中。 如果该文件包含多个 PowerShell 工作流,则导入将失败。 必须将每个工作流保存到各自的文件中,并分别导入每个工作流。
请勿将包含 PowerShell 工作流的 .ps1 文件导入 PowerShell Runbook,因为 PowerShell 脚本引擎无法识别它。
仅可将 .graphrunbook 文件导入到新的 图形运行手册 中。
通过 Azure 门户导入运行手册
可通过以下过程将脚本文件导入 Azure 自动化。
注意
只能通过门户将 .ps1 文件导入到 PowerShell 工作流 Runbook 中。
- 在 Azure 门户中,搜索并选择“自动化帐户”。
- 在“自动化帐户”页上,从列表中选择你的自动化帐户。
- 在自动化帐户中,选择流程自动化下的运行簿以打开运行簿列表。
- 单击 导入运行手册。 可以选择以下任一选项:
- 浏览文件 - 从本地计算机中选择文件。
- 从资源库中浏览 - 您可以从资源库中浏览并选择现有的运行手册。
- 选择文件。
- 如果启用了 名称 字段,你可以更改运行手册名称。 该名称必须以字母开头,可包含字母、数字、下划线和短划线。
- Runbook 类型会自动填充,但在考虑到适用限制的情况下,您可以更改该类型。
- “运行时版本”可以自动填充,也可以从下拉列表中选择版本。
- 单击“导入”。 新的运行手册会显示在该自动化帐户的运行手册列表中。
- 必须先发布运行手册,才能运行它。
注意
导入图形运行手册后,可将其转换为另一种类型。 但是,不能将图形化 Runbook 转换为文本式 Runbook。
使用 PowerShell 导入运行簿
使用 Import-AzAutomationRunbook cmdlet 将脚本文件导入为草稿运行簿。 如果该 Runbook 已存在,则导入将失败,除非你将 Force 参数与 cmdlet 一起使用。
以下示例演示了如何将脚本文件导入到 Runbook 中。
$params = @{
AutomationAccountName = 'MyAutomationAccount'
Name = 'Sample_TestRunbook'
ResourceGroupName = 'MyResourceGroup'
Type = 'PowerShell'
Path = 'C:\Runbooks\Sample_TestRunbook.ps1'
}
Import-AzAutomationRunbook @params
管理资源
如果你的 runbook 创建了资源,脚本应在尝试创建该资源之前先检查其是否已存在。 下面是一个基本示例。
$vmName = 'WindowsVM1'
$rgName = 'MyResourceGroup'
$myCred = Get-AutomationPSCredential 'MyCredential'
$vmExists = Get-AzResource -Name $vmName -ResourceGroupName $rgName
if (-not $vmExists) {
Write-Output "VM $vmName does not exist, creating"
New-AzVM -Name $vmName -ResourceGroupName $rgName -Credential $myCred
} else {
Write-Output "VM $vmName already exists, skipping"
}
从活动日志中检索详细信息
你可以从自动化帐户的活动日志中检索到运行簿详细信息,例如启动运行簿的人员或帐户。 以下 PowerShell 示例显示了运行指定 Runbook 的最后一名用户。
$rgName = 'MyResourceGroup'
$accountName = 'MyAutomationAccount'
$runbookName = 'MyRunbook'
$startTime = (Get-Date).AddDays(-1)
$params = @{
ResourceGroupName = $rgName
StartTime = $startTime
}
$JobActivityLogs = (Get-AzLog @params).Where( { $_.Authorization.Action -eq 'Microsoft.Automation/automationAccounts/jobs/write' })
$JobInfo = @{}
foreach ($log in $JobActivityLogs) {
# Get job resource
$JobResource = Get-AzResource -ResourceId $log.ResourceId
if ($null -eq $JobInfo[$log.SubmissionTimestamp] -and $JobResource.Properties.Runbook.Name -eq $runbookName) {
# Get runbook
$jobParams = @{
ResourceGroupName = $rgName
AutomationAccountName = $accountName
Id = $JobResource.Properties.JobId
}
$Runbook = Get-AzAutomationJob @jobParams | Where-Object RunbookName -EQ $runbookName
# Add job information to hashtable
$JobInfo.Add($log.SubmissionTimestamp, @($Runbook.RunbookName, $Log.Caller, $JobResource.Properties.jobId))
}
}
$JobInfo.GetEnumerator() | Sort-Object Key -Descending | Select-Object -First 1
跟踪进度
一个良好的做法是,以模块化方式编写 Runbook,使其中的逻辑易于重用并可轻松重新启动。 跟踪 Runbook 中的执行进度可确保在出现问题时,Runbook 逻辑能够正确执行。
你可以使用外部来源(例如存储帐户、数据库或共享文件)来跟踪运行手册的进度。 在 runbook 中添加逻辑,首先检查上一次执行的操作状态。 然后,逻辑可以根据检查结果跳过或继续执行 runbook 中的特定任务。
预防并发作业
如果某些运行手册同时在多个作业中运行,其行为可能会异常。 在这种情况下,runbook 需要实现相应的逻辑,以判断是否已经有作业正在运行。 下面是一个基本示例。
# Ensures you do not inherit an AzContext in your runbook
Disable-AzContextAutosave -Scope Process
# Connect to Azure with system-assigned managed identity
$AzureContext = (Connect-AzAccount -Environment AzureChinaCloud -Identity).context
# set and store context
$AzureContext = Set-AzContext -SubscriptionName $AzureContext.Subscription -DefaultProfile $AzureContext
# Check for already running or new runbooks
$runbookName = "runbookName"
$resourceGroupName = "resourceGroupName"
$automationAccountName = "automationAccountName"
$jobs = Get-AzAutomationJob -ResourceGroupName $resourceGroupName -AutomationAccountName $automationAccountName -RunbookName $runbookName -DefaultProfile $AzureContext
# Ranking all the active jobs
$activeJobs = $jobs | where {$_.status -eq 'Running' -or $_.status -eq 'Queued' -or $_.status -eq 'New' -or $_.status -eq 'Activating' -or $_.status -eq 'Resuming'} | Sort-Object -Property CreationTime
$jobRanking = @()
$rank = 0
ForEach($activeJob in $activeJobs)
{
$rank = $rank + 1
$activeJob | Add-Member -MemberType NoteProperty -Name jobRanking -Value $rank -Force
$jobRanking += $activeJob
}
$AutomationJobId = $PSPrivateMetadata.JobId.Guid
$currentJob = $activeJobs | where {$_.JobId -eq $AutomationJobId}
$currentJobRank = $currentJob.jobRanking
# Only allow the Job with Rank = 1 to start processing.
If($currentJobRank -ne "1")
{
Write-Output "$(Get-Date -Format yyyy-MM-dd-hh-mm-ss.ffff) Concurrency check failed as Current Job Ranking is not 1 but $($currentJobRank) therefore exiting..."
Exit
} Else
{
Write-Output "$(Get-Date -Format yyyy-MM-dd-hh-mm-ss.ffff) Concurrency check passed. Start processing.."
}
如果希望 Runbook 使用系统分配的托管标识执行,请按原样保留代码。 如果希望使用用户分配的托管标识,则执行以下操作:
- 从第 5 行中删除
$AzureContext = (Connect-AzAccount -Environment AzureChinaCloud -Identity).context, - 将其替换为
$AzureContext = (Connect-AzAccount -Environment AzureChinaCloud -Identity -AccountId <ClientId>).context,然后 - 输入客户端 ID。
注意
对于 PowerShell 7.2 混合作业,请更改第 28 行。 将 $PSPrivateMetadata.JobId.Guid 替换为 $env:PSPrivateMetaData。
处理依赖时间的脚本中的暂时性错误
运行手册必须足够健壮,并且能够处理错误,包括可能导致其重启或失败的瞬时错误。 如果运行手册失败,Azure 自动化将重试该运行手册。
如果你的运行手册通常需要在时间限制内运行,请在脚本中实现检查执行时间的逻辑。 该项检查可确保启动、关闭或横向扩展等操作仅在特定时间执行。
注意
Azure 沙盒进程的本地时间设为 UTC。 在 Runbook 中对日期和时间进行计算时,必须将这一点考虑在内。
Runbook 中用于避免瞬时故障的重试逻辑
Runbook 通常通过 ARM、Azure Resource Graph、SQL 服务和其他 Web 服务对 Azure 等远程系统发出调用。 当运行手册调用的系统处于繁忙状态、暂时不可用,或在负载较高时实施节流时,这些调用容易发生运行时错误。 若要在 Runbook 中构建复原能力,必须在发出调用时实现重试逻辑,使 Runbook 能够处理暂时性问题而不失败。
有关详细信息,请参阅重试模式以及 REST 和重试一般指导。
示例 1:如果运行手册仅进行一两次调用
$searchServiceURL = "https://$searchServiceName.search.chinacloudapi.cn"
$resource = Get-AzureRmResource -ResourceType "Microsoft.Search/searchServices" -ResourceGroupName $searchResourceGroupName -ResourceName $searchServiceName -ApiVersion 2015-08-19
$searchAPIKey = (Invoke-AzureRmResourceAction -Action listAdminKeys -ResourceId $resource.ResourceId -ApiVersion 2015-08-19 -Force).PrimaryKey
调用 Invoke-AzureRmResourceAction 时,你可能会遇到暂时性故障。 在这种情况下,我们建议您在调用 cmdlet 时采用以下基本模式。
$searchServiceURL = "https://$searchServiceName.search.chinacloudapi.cn"
$resource = Get-AzureRmResource -ResourceType "Microsoft.Search/searchServices" -ResourceGroupName $searchResourceGroupName -ResourceName $searchServiceName -ApiVersion 2015-08-19
# Adding in a retry
$Stoploop = $false
$Retrycount = 0
do {
try {
$searchAPIKey = (Invoke-AzureRmResourceAction -Action listAdminKeys -ResourceId $resource.ResourceId -ApiVersion 2015-08-19 -Force).PrimaryKey
write-verbose "Invoke-AzureRmResourceAction on $resource.ResourceId completed"
$Stoploop = $true
}
catch {
if ($Retrycount -gt 3)
{
Write-verbose "Could not Invoke-AzureRmResourceAction on $resource.ResourceId after 3 retrys."
$Stoploop = $true
}
else
{
Write-verbose "Could not Invoke-AzureRmResourceAction on $resource.ResourceId retrying in 30 seconds..."
Start-Sleep -Seconds 30
$Retrycount = $Retrycount + 1
}
}
}
While ($Stoploop -eq $false)
注意
最多重试调用三次,每次休眠 30 秒。
示例 2:如果运行手册频繁进行远程调用
如果 Runbook 频繁发出远程调用,则它可能会遇到暂时性运行时问题。 创建一个函数用于为发出的每个调用实现重试逻辑,并将要发出的调用作为要执行的脚本块传入。
Function ResilientRemoteCall {
param(
$scriptblock
)
$Stoploop = $false
$Retrycount = 0
do {
try {
Invoke-Command -scriptblock $scriptblock
write-verbose "Invoked $scriptblock completed"
$Stoploop = $true
}
catch {
if ($Retrycount -gt 3)
{
Write-verbose "Invoked $scriptblock failed 3 times and we will not try again."
$Stoploop = $true
}
else
{
Write-verbose "Invoked $scriptblock failed retrying in 30 seconds..."
Start-Sleep -Seconds 30
$Retrycount = $Retrycount + 1
}
}
}
While ($Stoploop -eq $false)
}
然后,您可以将每个远程调用作为参数传递给该函数,如
ResilientRemoteCall { Get-AzVm } 或
ResilientRemoteCall { $searchAPIKey = (Invoke-AzureRmResourceAction -Action listAdminKeys -ResourceId $resource.ResourceId -ApiVersion 2015-08-19 -Force).PrimaryKey}
使用多个订阅
你的运行手册必须能够适用于订阅。 例如,Runbook 会使用 Disable-AzContextAutosave cmdlet 来处理多个订阅。 该 cmdlet 可确保不从正在同一沙盒中运行的另一 Runbook 中检索身份验证上下文。
# Ensures you do not inherit an AzContext in your runbook
Disable-AzContextAutosave -Scope Process
# Connect to Azure with system-assigned managed identity
$AzureContext = (Connect-AzAccount -Environment AzureChinaCloud -Identity).context
# set and store context
$AzureContext = Set-AzContext -SubscriptionName $AzureContext.Subscription `
-DefaultProfile $AzureContext
$childRunbookName = 'childRunbookDemo'
$resourceGroupName = "resourceGroupName"
$automationAccountName = "automationAccountName"
$startParams = @{
ResourceGroupName = $resourceGroupName
AutomationAccountName = $automationAccountName
Name = $childRunbookName
DefaultProfile = $AzureContext
}
Start-AzAutomationRunbook @startParams
如果希望 Runbook 使用系统分配的托管标识执行,请按原样保留代码。 如果希望使用用户分配的托管标识,则执行以下操作:
- 从第 5 行中删除
$AzureContext = (Connect-AzAccount -Environment AzureChinaCloud -Identity).context, - 将其替换为
$AzureContext = (Connect-AzAccount -Environment AzureChinaCloud -Identity -AccountId <ClientId>).context,然后 - 输入客户端 ID。
使用自定义脚本
注意
通常无法在已安装 Log Analytics 代理的主机上运行自定义脚本和 Runbook。
若要使用自定义脚本:
- 创建自动化帐户。
- 部署混合 Runbook 工作器角色。
测试运行手册
测试运行手册时,将执行草稿版本,并完成其执行的所有操作。 不会创建作业历史记录,但会在“测试输出”窗格中显示输出与警告和错误。 仅当 VerbosePreference 变量设置为 Continue 时,发送到 详细流 的消息才会显示在“输出”窗格中。
即使当前运行的是草稿版本,运行手册仍会正常执行,并对环境中的资源执行相应操作。 因此,您应仅在非生产资源上测试运行手册。
注意
所有 runbook 执行操作都记录在自动化帐户的“活动日志”中,操作名称为“创建Azure 自动化作业”。 但是,在测试窗格中执行 runbook 草稿版本时,该 runbook 执行会在活动日志中记录为操作名称 Write an Azure 自动化 runbook draft。 选择Operation和JSON选项卡,以查看以../runbooks/(runbook name)/draft/testjob结尾的作用域。
测试每种运行手册类型的流程都相同。 在 Azure 门户中,文本编辑器和图形编辑器的测试没有区别。
- 在文本编辑器或图形编辑器中打开 Runbook 的草稿版本。
- 单击“测试”打开测试页面 。
- 如果 Runbook 具有参数,它们会在左窗格中列出,你可在这里提供要用于测试的值。
- 若要在混合 Runbook 辅助角色上运行测试,请将运行设置更改为混合辅助角色,并选择目标组名称。 否则,保留默认值 Azure,以在云中运行测试。
- 单击“启动”,开始测试。
- 在测试期间,可使用“输出”窗格下面的按钮来停止或暂停 PowerShell 工作流或图形 Runbook。 当您暂停运行手册时,它会先完成当前活动,然后再暂停。 暂停 Runbook 后,可以将它停止或重启。
- 在Output窗格中检查运行手册的输出。
发布运行手册
创建或导入新的 Runbook 后,必须先将其发布,才能运行它。 Azure 自动化中的每个 Runbook 都有一个草稿版本和一个已发布版本。 只有已发布版才能用来运行,只有草稿版才能用来编辑。 已发布版不受对草稿版所做的任何更改的影响。 当应该提供草稿版本时,你要发布它,使用草稿版本覆盖当前的已发布版本。
在 Azure 门户中发布运行手册
- 在 Azure 门户中,搜索并选择“自动化帐户”。
- 在“自动化帐户”页上,从列表中选择你的自动化帐户。
- 在你的 Automation 帐户中打开运行手册。
- 单击 “编辑” 。
- 单击“发布”,然后在对验证消息的响应中选择“是” 。
使用 PowerShell 发布 Runbook
使用 Publish-AzAutomationRunbook cmdlet 发布你的运行手册。
$accountName = "MyAutomationAccount"
$runbookName = "Sample_TestRunbook"
$rgName = "MyResourceGroup"
$publishParams = @{
AutomationAccountName = $accountName
ResourceGroupName = $rgName
Name = $runbookName
}
Publish-AzAutomationRunbook @publishParams
在 Azure 门户中计划运行手册
当你的运行手册发布后,你可以安排其运行:
- 在 Azure 门户中,搜索并选择“自动化帐户”。
- 在“自动化帐户”页上,从列表中选择你的自动化帐户。
- 从你的运行手册列表中选择一个运行手册。
- 在“资源”下选择“计划”。
- 选择“添加计划”。
- 在“计划 Runbook”窗格中,选择“将计划关联到 Runbook” 。
- 在“计划”窗格中选择“创建新计划” 。
- 在“新建计划”窗格中输入名称、说明和其他参数。
- 创建计划后,将其突出显示并单击“确定”。 它现应与你的 Runbook 关联。
- 请留意邮箱中有关 Runbook 状态的通知邮件。
恢复已删除的运行手册
可以通过 PowerShell 脚本恢复已删除的 Runbook。 要恢复运行手册,请确保满足以下条件:
- 要还原的 Runbook 已在过去 29 天内被删除。
- 该 Runbook 的自动化帐户存在。
- 自动化帐户的系统分配托管标识已被授予 自动化参与者 角色权限。
PowerShell 脚本
- 在自动化帐户中以作业形式运行 PowerShell 脚本,以还原已删除的 Runbook。
- 从 GitHub 下载 PowerShell 脚本。 或者,您可以从 Runbook 库导入名为 Restore Automation runbook 的 PowerShell 脚本。 提供要恢复的 Runbook 名称,并在 Azure 自动化 中将其作为作业运行,以恢复已删除的 Runbook。
- 从 GitHub 下载脚本,或从 Runbook Gallery 导入名为列出已删除的自动化 Runbook的 PowerShell 脚本,用于识别过去 29 天内已删除的 Runbook 名称。
获取作业状态
在 Azure 门户中查看状态
有关 Azure 自动化中的作业处理的详细信息,请参阅作业。 当你准备好查看运行簿作业时,请使用 Azure 门户访问你的自动化帐户。 在右侧,你可以在 作业统计信息 中查看所有 Runbook 作业的摘要。
该摘要显示了所执行的每项作业的状态的计数和图形表示形式。
单击磁贴可显示“作业”页面,其中有所执行的全部作业的汇总列表。 该页面会显示每项作业的状态、Runbook 名称、开始时间和完成时间。
您可以通过选择筛选作业来筛选作业列表。 按特定 Runbook、作业状态或下拉列表中的某个选项进行筛选,并指定搜索的时间范围。
或者,你也可以在自动化帐户中的“Runbook”页面上选择某个特定的 Runbook,然后选择 Jobs 以查看该 Runbook 的作业摘要详细信息。 该操作会显示“作业”页面。 你可在这里单击作业记录,查看它的详细信息和输出内容。
使用 PowerShell 检索作业状态
使用 Get-AzAutomationJob cmdlet 获取为 runbook 创建的作业以及特定作业的详细信息。 如果使用 Start-AzAutomationRunbook 启动 Runbook,它会返回生成的作业。 使用 Get-AzAutomationJobOutput 检索作业输出。
以下示例会获取示例 Runbook 的最后一项作业,并显示它的状态、为 Runbook 参数提供的值以及作业的输出内容。
$getJobParams = @{
AutomationAccountName = 'MyAutomationAccount'
ResourceGroupName = 'MyResourceGroup'
Runbookname = 'Test-Runbook'
}
$job = (Get-AzAutomationJob @getJobParams | Sort-Object LastModifiedDate -Desc)[0]
$job | Select-Object JobId, Status, JobParameters
$getOutputParams = @{
AutomationAccountName = 'MyAutomationAccount'
ResourceGroupName = 'MyResourceGroup'
Id = $job.JobId
Stream = 'Output'
}
Get-AzAutomationJobOutput @getOutputParams
以下示例会检索特定作业的输出,并返回每条记录。 如果其中一个记录出现异常,脚本将写出异常而不是值。 此行为非常有用,因为异常可提供在输出过程中可能无法正常记录的其他信息。
$params = @{
AutomationAccountName = 'MyAutomationAccount'
ResourceGroupName = 'MyResourceGroup'
Stream = 'Any'
}
$output = Get-AzAutomationJobOutput @params
foreach ($item in $output) {
$jobOutParams = @{
AutomationAccountName = 'MyAutomationAccount'
ResourceGroupName = 'MyResourceGroup'
Id = $item.StreamRecordId
}
$fullRecord = Get-AzAutomationJobOutputRecord @jobOutParams
if ($fullRecord.Type -eq 'Error') {
$fullRecord.Value.Exception
} else {
$fullRecord.Value
}
}
后续步骤
- 有关示例查询,请参阅作业日志和作业流的示例查询
- 若要了解 Runbook 管理的详细信息,请参阅在 Azure 自动化中执行 Runbook。
- 有关在管理 Runbook 时运行时版本支持和弃用的信息,请参阅 Azure 自动化 的语言运行时支持和弃用策略。
- 若要创建 PowerShell 运行簿,请参阅 在 Azure 自动化 中编辑文本运行簿。
- 要排查运行手册执行问题,请参阅排查运行手册问题。