Windows PowerShell 工作流概念
Service Management Automation 的一 种类型的 Runbook 基于 Windows PowerShell 工作流。 本文简要概述了自动化 Runbook 中常见的工作流的关键功能。 有关工作流的完整详细信息可在 Windows PowerShell 工作流简介中找到。
Service Management Automation 的 Runbook 和 Microsoft Azure 自动化 的 Runbook 结构相同,尽管这两者通常适用于不同的资源。
Windows PowerShell 工作流
工作流是一系列经过编程的连接步骤,会执行长期运行的任务,或是需要在多个设备或托管节点之间协调多个步骤。 与标准脚本相比,工作流的好处包括能够同时执行针对多台设备的操作以及自动从故障中恢复的能力。 Windows PowerShell 工作流是使用 Windows Workflow Foundation 的 Windows PowerShell 脚本。 虽然工作流是使用 Windows PowerShell 语法编写的,并由 Windows PowerShell 启动,但它由 Windows Workflow Foundation 处理。
基本结构
Windows PowerShell 工作流以 Workflow 关键字开头,后跟大括号括起来的脚本正文。 工作流名称跟在 Workflow 关键字之后,如以下语法中所示。 工作流的名称与自动化 Runbook 的名称匹配。
Workflow Test-Runbook
{
<Commands>
}
若要将参数添加到工作流,请使用 Param 关键字,如以下语法所示。 管理门户将提示用户在启动 Runbook 时提供这些参数的值。 此示例使用可选的 Parameter 属性,该属性指定参数是否是必需的。
Workflow Test-Runbook
{
Param
(
[Parameter(Mandatory=<$True | $False>]
[Type]$<ParameterName>,
[Parameter(Mandatory=<$True | $False>]
[Type]$<ParameterName>
)
<Commands>
}
命名
工作流的名称应遵守“动词-名词”格式,该格式是 Windows PowerShell 的标准。 你可以参阅 Approved Verbs for Windows PowerShell Commands(Windows PowerShell Commands 批准使用的动词) 以了解批准使用的动词的列表。 工作流名称与自动化 Runbook 的名称匹配。 如果正在导入某个 Runbook,其文件名必须与工作流名称匹配,并且必须以 .ps1 结尾。
限制
有关限制以及 Windows PowerShell 工作流和 Windows PowerShell 之间的语法差异的完整列表,请参阅 脚本工作流和脚本之间的语法差异。
活动
活动是工作流中的特定任务。 就像脚本由一个或多个命令构成一样,工作流由一个或多个按顺序执行的活动构成。 Windows PowerShell 工作流在运行工作流时,会自动将许多 Windows PowerShell cmdlet 转换为活动。 在 Runbook 中指定其中的某个 cmdlet 时,相应的活动实际上由 Windows Workflow Foundation 运行。 对于没有相应活动的 cmdlet,Windows PowerShell 工作流会自动在 InlineScript 活动中运行 cmdlet。 除非在 InlineScript 块中显式包含它们,否则工作流中存在一组被排除且不能在工作流中使用的 cmdlet。 有关这些概念的详细信息,请参阅 在脚本工作流中使用活动。
工作流活动共享一组公用参数来配置其操作。 有关工作流通用参数的详细信息,请参阅 about_WorkflowCommonParameters。
集成模块
集成模块是包含 Windows PowerShell 模块的包,可以导入到自动化中。 Windows PowerShell 模块包含可在自动化 Runbook 中使用的 cmdlet。 Operations Manager 和 Azure 等产品和服务具有包含特定于其操作的 cmdlet 模块。
导入到自动化的集成模块将自动适用于所有 Runbook。 由于自动化基于 Windows PowerShell 4.0,因此它支持自动加载模块,这意味着可以使用已安装模块中的 cmdlet,而无需使用 Import-Module 将其导入脚本。
只要所有 Windows PowerShell 模块都可以导入到自动化中,只要其所有依赖项都可以位于单个文件夹中。 如果模块依赖于不在默认路径中的注册表设置或文件,则可以导入它,但它很可能不起作用,因为自动化无法找到其依赖项。 具有外部依赖项的模块可用于 Runbook 中,方法是将它们安装到使用的另一台主机上,然后使用 InlineScript 脚本块访问它们。
借助 Service Management Automation,可以通过在每个辅助角色服务器上安装具有外部依赖项的模块。 虽然这些模块中的 cmdlet 可以在 Runbook 中使用,但自动化不会发现它们以支持“插入活动”向导等功能。 为了使用此功能,你可以使用 New-SmaPortableModule cmdlet 创建一个便携模块。 此 cmdlet 创建一个模块,其中包含其每个 cmdlet 的存根,并且可以导入到自动化中。 当 Runbook 使用其中一个 cmdlet 时,存根会将调用重定向到外部模块中的实际 cmdlet。 该模块必须安装在每个 Worker 服务器上,否则调用将失败。
并行执行
Windows PowerShell 工作流的一个优点是能够与典型脚本一样并行而不是按顺序执行一组命令。 这一点在 Runbook 中特别有用,因为它们可能会执行要花很长时间才能完成的多个操作。 例如,Runbook 可能会设置一组虚拟机。 可以同时执行这些操作,而不是按顺序执行每个预配过程,从而提高整体效率。 只有当所有操作都完成后,Runbook 才会继续。
可以使用 Parallel 关键字创建可同时运行的含多个命令的脚本块。 这会使用如下所示的语法。 在这种情况下,Activity1 和 Activity2 将同时启动。 只有在 Activity1 和 Activity2 已完成后,activity3 才会启动。
Parallel
{
<Activity1>
<Activity2>
}
<Activity3>
可以使用 ForEach-Parallel 构造同时处理集合中每个项的命令。 尽管脚本块中的命令按顺序运行,但集合中的项是并行处理的。 这会使用如下所示的语法。 在这种情况下,Activity1 将同时针对集合中的所有项启动。 对于每个项,Activity2 会在 Activity1 完成后启动。 只有在 Activity1 和 Activity2 都已完成所有项之后,Activity3 才会启动。
ForEach -Parallel ($<item> in $<collection>)
{
<Activity1>
<Activity2>
}
<Activity3>
Sequence 关键字用于在并行脚本块中按顺序运行命令。 Sequence 脚本块与其他命令并行运行,但块中的命令按顺序运行。 这会使用如下所示的语法。 在此例中,Activity1、Activity2 和 Activity3 将同时启动。 只有在 Activity3 完成后,Activity4 才会启动。 活动 5 将在完成所有其他活动后启动
Parallel
{
<Activity1>
<Activity2>
Sequence
{
<Activity3>
<Activity4>
}
}
<Activity5>
检查点
“检查点”是工作流当前状态的快照,其中包括变量的当前值以及到该点为止生成的任何输出。 Runbook 中要完成的最后一个检查点将保存到自动化数据库,以便即使在中断的情况下,工作流也能恢复。 Runbook 作业完成后,将删除检查点数据。
可以使用 Checkpoint-Workflow 活动在工作流中设置一个检查点。 如果将此活动包括在 Runbook 中,则会立即获取检查点。 如果 Runbook 由于错误而挂起,则在作业恢复后,它将从设置的最后一个检查点的位置处恢复。
在以下示例代码中,Activity2 之后发生错误,导致 Runbook 挂起。 作业恢复后,它将从运行 Activity2 开始,因为这正在设置的最后一个检查点后。
<Activity1>
Checkpoint-Workflow
<Activity2>
<Error>
<Activity3>
应该在 Runbook 中设置检查点,在可能容易出错的活动之后设置检查点,如果恢复 Runbook,则不应重复。 例如,你的 Runbook 可能创建虚拟机。 可以在命令之前和之后设置一个检查点以创建虚拟机。 如果创建失败,则命令会在 Runbook 恢复后重复。 如果创建成功,但 Runbook 稍后会失败,则在恢复 Runbook 时,不会再次创建虚拟机。
关于检查点的详细信息,请参阅向脚本工作流添加检查点。
挂起 Runbook
可以强制 Runbook 使用 Suspend-Workflow 活动来暂停自身。 此活动将设置一个检查点,并使工作流立即挂起。 对于可能需要在运行另一组活动运行之前执行手动步骤的 Runbook,挂起工作流十分有用。
有关挂起工作流的详细信息,请参阅 Making a Workflow Suspend Itself(让工作流挂起自身)。
InlineScript
InlineScript 活动在单独的非工作流会话中运行命令块,并将其输出返回到工作流。 尽管工作流中的命令将发送到 Windows Workflow Foundation 进行处理,但 InlineScript 块中的命令由 Windows PowerShell 处理。 活动使用标准工作流通用参数(包括 PSComputerName 和 PSCredential),该参数允许指定代码块在另一台计算机上运行或使用备用凭据。
InlineScript 使用如下所示的语法。
InlineScript
{
<Script Block>
} <Common Parameters>
Runbook 中 InlineScript 的最常见用途是在另一台计算机上运行代码块。 如果 Runbook 中的 cmdlet 未安装在自动化中,或者该操作仅具有在本地在目标计算机上执行的权限,则需要此操作。 下面的图表中阐释了这一点。
为了在另一台计算机上运行代码块, PSComputer 和 PSCredential 参数用于 InlineScript 活动。 通常在 Runbook 中使用 Credential 或 Connection 等全局资源为这些参数提供值。 下面的示例代码在由名为 MyConnection 的连接表示的计算机上运行一组命令。
$con = Get-AutomationConnection -Name 'MyConnection'
$securepassword = ConvertTo-SecureString -AsPlainText -String $con.Password -Force
$cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $con.Username, $securepassword
InlineScript
{
<Commands>
} -PSComputer $con.ComputerName -PSCredential $cred
虽然 InlineScript 活动在某些 Runbook 中可能至关重要,但仅在必要时才应出于以下原因使用它们:
不能在 InlineScript 块中使用检查点。 如果块内出现故障,则必须从头开始恢复块。
InlineScript 会影响 Runbook 的可伸缩性,因为它保留 InlineScript 块的整个长度的 Windows PowerShell 会话。
InlineScript 块中不提供 Get-AutomationVariable 和 Get-AutomationPSCredential 等活动。
如果需要使用 InlineScript,则应将其范围降到最低。 例如,如果 Runbook 在对每个项应用相同的操作时循环访问集合,则循环应在 InlineScript 外部发生。 这将提供下列优势:
你可在每个迭代后 检查 工作流。 如果作业挂起或中断并进行恢复,则循环将能够恢复。
可以使用 ForEach“并行 处理收集项”。
如果在 Runbook 中使用 InlineScript ,请记住以下建议:
你可以使用 $Using 作用域修饰符将值传入脚本。 例如,在 InlineScript 外部设置的名为 $abc 的变量将成为 InlineScript 中的 $using:abc。
若要从 InlineScript 返回输出,请将输出分配给变量,并输出要返回到输出流的任何数据。 以下示例将字符串 hi 分配给名为 $output 的变量。
$output = InlineScript { Write-Output "hi" }
避免在 InlineScript 范围内定义工作流。 尽管某些工作流可能看起来正常运行,但这不是经过测试的方案。 因此,你可能会遇到令人困惑的错误消息或意外的行为。
有关使用 InlineScript 的详细信息,请参阅 在工作流 中运行 Windows PowerShell 命令并 about_InlineScript。