您现在访问的是微软AZURE全球版技术文档网站,若需要访问由世纪互联运营的MICROSOFT AZURE中国区技术文档网站,请访问 https://docs.azure.cn.

了解自动化 runbook 的关键 PowerShell 工作流概念Learning key Windows PowerShell Workflow concepts for Automation runbooks

Azure 自动化中的 Runbook 作为 Windows PowerShell 工作流实现。Runbooks in Azure Automation are implemented as Windows PowerShell Workflows. Windows PowerShell 工作流类似于 Windows PowerShell 脚本,但包括一些可能会让新用户产生混淆的重大差异。A Windows PowerShell Workflow is similar to a Windows PowerShell script but has some significant differences that can be confusing to a new user. 本文旨在提供有关使用 PowerShell 工作流编写 runbook 的帮助,但我们建议使用 PowerShell 编写 runbook,除非是需要检查点的情况。While this article is intended to help you write runbooks using PowerShell workflow, we recommend you write runbooks using PowerShell unless you need checkpoints. 编写 PowerShell 工作流 runbook 时存在几个语法差异,这些差异会增加编写有效工作流时所需的工作量。There are several syntax differences when authoring PowerShell Workflow runbooks and these differences require a bit more work to write effective workflows.

工作流是一系列编程的连接步骤,用于执行长时间运行的任务,或者要求跨多个设备或托管节点协调多个步骤。A workflow is a sequence of programmed, connected steps that perform long-running tasks or require the coordination of multiple steps across multiple devices or managed nodes. 与标准脚本相比,工作流的好处包括能够同时执行针对多台设备的操作以及自动从故障中恢复的能力。The benefits of a workflow over a normal script include the ability to simultaneously perform an action against multiple devices and the ability to automatically recover from failures. Windows PowerShell 工作流是使用 Windows Workflow Foundation 的 Windows PowerShell 脚本。A Windows PowerShell Workflow is a Windows PowerShell script that uses Windows Workflow Foundation. 尽管工作流是使用 Windows PowerShell 语法编写的并通过 Windows PowerShell 启动,但它由 Windows Workflow Foundation 进行处理。While the workflow is written with Windows PowerShell syntax and launched by Windows PowerShell, it is processed by Windows Workflow Foundation.

有关本文中主题的完整详细信息,请参阅 Windows PowerShell 工作流简介For complete details on the topics in this article, see Getting Started with Windows PowerShell Workflow.

工作流的基本结构Basic structure of a workflow

将 PowerShell 脚本转换为 PowerShell 工作流的第一步是使用 Workflow 关键字将其括起来。The first step to converting a PowerShell script to a PowerShell workflow is enclosing it with the Workflow keyword. 工作流以 Workflow 关键字开头,后接括在大括号中的脚本正文。A workflow starts with the Workflow keyword followed by the body of the script enclosed in braces. 工作流名称跟在 Workflow 关键字之后,如以下语法中所示:The name of the workflow follows the Workflow keyword as shown in the following syntax:

Workflow Test-Workflow
{
   <Commands>
}

工作流名称与自动化 Runbook 的名称匹配。The name of the workflow must match the name of the Automation runbook. 如果正在导入某个 Runbook,其文件名必须与工作流名称匹配,并且必须以 .ps1 结尾。If the runbook is being imported, then the filename must match the workflow name and must end in .ps1.

要将参数添加到工作流,请使用 Param 关键字,与使用脚本时相同。To add parameters to the workflow, use the Param keyword just as you would to a script.

代码更改Code changes

除了几个重大更改以外,PowerShell 工作流代码看起来几乎与 PowerShell 脚本代码完全相同。PowerShell workflow code looks almost identical to PowerShell script code except for a few significant changes. 以下各部分介绍要使 PowerShell 脚本能够在工作流中运行所需进行的更改。The following sections describe changes that you need to make to a PowerShell script for it to run in a workflow.

活动Activities

活动是工作流中的特定任务。An activity is a specific task in a workflow. 就像脚本由一个或多个命令构成一样,工作流由一个或多个按顺序执行的活动构成。Just as a script is composed of one or more commands, a workflow is composed of one or more activities that are carried out in a sequence. Windows PowerShell 工作流在运行工作流时,会自动将许多 Windows PowerShell cmdlet 转换为活动。Windows PowerShell Workflow automatically converts many of the Windows PowerShell cmdlets to activities when it runs a workflow. 在 Runbook 中指定其中的某个 cmdlet 时,相应的活动由 Windows Workflow Foundation 运行。When you specify one of these cmdlets in your runbook, the corresponding activity is run by Windows Workflow Foundation. 对于这些没有相应活动的 cmdlet,Windows PowerShell 工作流会自动在 InlineScript 活动中运行该 cmdlet。For those cmdlets without a corresponding activity, Windows PowerShell Workflow automatically runs the cmdlet within an InlineScript activity. 有一组 cmdlet 已被排除,不能包含在工作流中,除非显式将它们包含在 InlineScript 块中。There is a set of cmdlets that are excluded and cannot be used in a workflow unless you explicitly include them in an InlineScript block. 有关这些概念的更多详细信息,请参阅在脚本工作流中使用活动For further details on these concepts, see Using Activities in Script Workflows.

工作流活动共享一组公用参数来配置其操作。Workflow activities share a set of common parameters to configure their operation. 有关工作流通用参数的详细信息,请参阅 about_WorkflowCommonParametersFor details about the workflow common parameters, see about_WorkflowCommonParameters.

位置参数Positional parameters

无法针对工作流中的活动和 cmdlet 使用位置参数。You can't use positional parameters with activities and cmdlets in a workflow. 这意味着必须使用参数名称。All this means is that you must use parameter names.

例如,请注意下面的代码,用于获取所有正在运行的服务。For example, consider the following code that gets all running services.

 Get-Service | Where-Object {$_.Status -eq "Running"}

如果尝试在工作流中运行此代码,将收到一条消息,类似于“无法使用指定的命名参数解析参数集”。If you try to run this same code in a workflow, you receive a message like "Parameter set cannot be resolved using the specified named parameters." 若要更正此问题,请提供如以下所示的参数名称。To correct this, provide the parameter name as in the following.

Workflow Get-RunningServices
{
    Get-Service | Where-Object -FilterScript {$_.Status -eq "Running"}
}

反序列化的对象Deserialized objects

工作流中的对象已反序列化。Objects in workflows are deserialized. 这意味着其属性仍然可用,但其方法不再可用。This means that their properties are still available, but not their methods. 例如,请注意以下 PowerShell 代码,使用服务对象的 Stop 方法停止一项服务。For example, consider the following PowerShell code that stops a service using the Stop method of the Service object.

$Service = Get-Service -Name MyService
$Service.Stop()

如果尝试在工作流中运行此代码,将收到错误消息,指出“在 Windows PowerShell 工作流中不支持方法调用”。If you try to run this in a workflow, you receive an error saying "Method invocation is not supported in a Windows PowerShell Workflow."

一种选择是将这两行代码包括在 InlineScript 代码块中,在这种情况下,$Service 是该代码块中的服务对象。One option is to wrap these two lines of code in an InlineScript block in which case $Service would be a service object within the block.

Workflow Stop-Service
{
    InlineScript {
        $Service = Get-Service -Name MyService
        $Service.Stop()
    }
}

另一个选项是使用执行相同功能的另一个 cmdlet(如果可用)。Another option is to use another cmdlet that performs the same functionality as the method, if one is available. 在我们的示例中,Stop-Service cmdlet 提供了与 Stop 方法相同的功能,可以将以下代码用于工作流。In our sample, the Stop-Service cmdlet provides the same functionality as the Stop method, and you could use the following for a workflow.

Workflow Stop-MyService
{
    $Service = Get-Service -Name MyService
    Stop-Service -Name $Service.Name
}

InlineScriptInlineScript

需要将一个或多个命令作为传统 PowerShell 脚本而不是 PowerShell 工作流运行时,InlineScript 活动非常有用。The InlineScript activity is useful when you need to run one or more commands as traditional PowerShell script instead of PowerShell workflow. 尽管工作流中的命令将发送到 Windows Workflow Foundation 进行处理,但 InlineScript 块中的命令由 Windows PowerShell 处理。While commands in a workflow are sent to Windows Workflow Foundation for processing, commands in an InlineScript block are processed by Windows PowerShell.

InlineScript 使用如下所示的语法。InlineScript uses the following syntax shown below.

InlineScript
{
  <Script Block>
} <Common Parameters>

可以通过将输出分配到一个变量,以返回来自 InlineScript 的输出。You can return output from an InlineScript by assigning the output to a variable. 下面的示例停止一项服务,并输出服务名称。The following example stops a service and then outputs the service name.

Workflow Stop-MyService
{
    $Output = InlineScript {
        $Service = Get-Service -Name MyService
        $Service.Stop()
        $Service
    }

    $Output.Name
}

可将值传递到 InlineScript 块,但必须使用 $Using 作用域修饰符。You can pass values into an InlineScript block, but you must use $Using scope modifier. 下面的示例与前面的示例相同,只是服务名称由变量提供。The following example is identical to the previous example except that the service name is provided by a variable.

Workflow Stop-MyService
{
    $ServiceName = "MyService"

    $Output = InlineScript {
        $Service = Get-Service -Name $Using:ServiceName
        $Service.Stop()
        $Service
    }

    $Output.Name
}

尽管 InlineScript 活动可能在某些工作流中非常关键,但它们不支持工作流构造,并且只能出于以下原因才使用:While InlineScript activities may be critical in certain workflows, they do not support workflow constructs and should only be used when necessary for the following reasons:

  • 不能在 InlineScript 块内部使用检查点You cannot use checkpoints inside an InlineScript block. 如果块中发生失败,它必须从块的开头恢复。If a failure occurs within the block, it must be resumed from the beginning of the block.
  • 不能在 InlineScriptBlock 内部使用并行执行You cannot use parallel execution inside an InlineScriptBlock.
  • 因为 InlineScript 会在 InlineScript 块的整个长度内占有 Windows PowerShell 会话,因此会影响工作流的可伸缩性。InlineScript affects scalability of the workflow since it holds the Windows PowerShell session for the entire length of the InlineScript block.

有关使用 InlineScript 的详细信息,请参阅在工作流中运行 Windows PowerShell 命令about_InlineScriptFor more information on using InlineScript, see Running Windows PowerShell Commands in a Workflow and about_InlineScript.

并行处理Parallel processing

Windows PowerShell 工作流的一个优点是能够与典型脚本一样并行而不是按顺序执行一组命令。One advantage of Windows PowerShell Workflows is the ability to perform a set of commands in parallel instead of sequentially as with a typical script.

可以使用 Parallel 关键字创建包含将同时运行的多个命令的脚本块。You can use the Parallel keyword to create a script block with multiple commands that run concurrently. 此脚本块使用如下所示的语法。This uses the following syntax shown below. 在此示例中,Activity1 和 Activity2 将同时启动。In this case, Activity1 and Activity2 starts at the same time. 只有在 Activity1 和 Activity2 完成后,Activity3 才会启动。Activity3 starts only after both Activity1 and Activity2 have completed.

Parallel
{
  <Activity1>
  <Activity2>
}
<Activity3>

例如,请注意以下将多个文件复制到网络目标的 PowerShell 命令。For example, consider the following PowerShell commands that copy multiple files to a network destination. 这些命令将依次进行,因此必须完成一个文件的复制,然后才能开始复制下一个文件。These commands are run sequentially so that one file must finish copying before the next is started.

Copy-Item -Path C:\LocalPath\File1.txt -Destination \\NetworkPath\File1.txt
Copy-Item -Path C:\LocalPath\File2.txt -Destination \\NetworkPath\File2.txt
Copy-Item -Path C:\LocalPath\File3.txt -Destination \\NetworkPath\File3.txt

下面的工作流并行运行这些命令,以便它们同时开始复制。The following workflow runs these same commands in parallel so that they all start copying at the same time. 只有在所有复制均已完成之后,才会显示完成消息。Only after they are all copied is the completion message displayed.

Workflow Copy-Files
{
    Parallel
    {
        Copy-Item -Path "C:\LocalPath\File1.txt" -Destination "\\NetworkPath"
        Copy-Item -Path "C:\LocalPath\File2.txt" -Destination "\\NetworkPath"
        Copy-Item -Path "C:\LocalPath\File3.txt" -Destination "\\NetworkPath"
    }

    Write-Output "Files copied."
}

可以使用 ForEach-Parallel 构造同时处理集合中每个项的命令。You can use the ForEach -Parallel construct to process commands for each item in a collection concurrently. 尽管脚本块中的命令按顺序运行,但集合中的项是并行处理的。The items in the collection are processed in parallel while the commands in the script block run sequentially. 此脚本块使用如下所示的语法。This uses the following syntax shown below. 在此示例中,将同时对集合中的所有项启动 Activity1。In this case, Activity1 starts at the same time for all items in the collection. 对于每个项,Activity2 会在 Activity1 完成后启动。For each item, Activity2 starts after Activity1 is complete. 只有在对所有项完成 Activity1 和 Activity2 后,Activity3 才会启动。Activity3 starts only after both Activity1 and Activity2 have completed for all items.

ForEach -Parallel ($<item> in $<collection>)
{
  <Activity1>
  <Activity2>
}
<Activity3>

下面的示例是类似于前面的示例,用于并行复制文件。The following example is similar to the previous example copying files in parallel. 在这种情况下,每个文件复制完成之后都会显示一条消息。In this case, a message is displayed for each file after it copies. 只有在所有文件均复制完成之后,才会显示最终的完成消息。Only after they are all completely copied is the final completion message displayed.

Workflow Copy-Files
{
    $files = @("C:\LocalPath\File1.txt","C:\LocalPath\File2.txt","C:\LocalPath\File3.txt")

    ForEach -Parallel ($File in $Files)
    {
        Copy-Item -Path $File -Destination \\NetworkPath
        Write-Output "$File copied."
    }

    Write-Output "All files copied."
}

备注

我们不建议并行运行子 Runbook,这是由于这已被证实将导致不可靠的结果。We do not recommend running child runbooks in parallel since this has been shown to give unreliable results. 子 Runbook 的输出有时不显示,一个子 Runbook 中的设置可能会影响其他并行子 RunbookThe output from the child runbook sometimes does not show up, and settings in one child runbook can affect the other parallel child runbooks

检查点Checkpoints

“检查点”是工作流当前状态的快照,其中包括变量的当前值以及到该点为止生成的任何输出。A checkpoint is a snapshot of the current state of the workflow that includes the current value for variables and any output generated to that point. 如果工作流以错误结束或暂停,则其下次运行时会从其上一个检查点开始,而不是从工作流的起点开始。If a workflow ends in error or is suspended, then the next time it is run it will start from its last checkpoint instead of the start of the worfklow. 可以使用 Checkpoint-Workflow 活动在工作流中设置一个检查点。You can set a checkpoint in a workflow with the Checkpoint-Workflow activity.

在以下示例代码中,Activity2 后发生的异常导致工作流结束。In the following sample code, an exception occurs after Activity2 causing the workflow to end. 当工作流再次运行时,它会通过运行 Activity2 来启动,因为此活动刚好在设置的上一个检查点之后。When the workflow is run again, it starts by running Activity2 since this was just after the last checkpoint set.

<Activity1>
Checkpoint-Workflow
<Activity2>
<Exception>
<Activity3>

应在可能容易出现异常并且在工作流继续时不应重复进行的活动之后设置检查点。You should set checkpoints in a workflow after activities that may be prone to exception and should not be repeated if the workflow is resumed. 例如,工作流可能会创建一个虚拟机。For example, your workflow may create a virtual machine. 可以在命令之前和之后设置一个检查点以创建虚拟机。You could set a checkpoint both before and after the commands to create the virtual machine. 如果创建失败,则当再次启动工作流时会重复命令。If the creation fails, then the commands would be repeated if the workflow is started again. 如果创建成功但工作流随后失败,则恢复工作流时不会再次创建虚拟机。If the worfklow fails after the creation succeeds, then the virtual machine will not be created again when the workflow is resumed.

下面的示例将多个文件复制到某个网络位置,并在每个文件复制完成后设置检查点。The following example copies multiple files to a network location and sets a checkpoint after each file. 如果网络位置丢失,则工作流以错误结束。If the network location is lost, then the workflow ends in error. 重新启动工作流时,它将从上一个检查点处继续,这意味着只会跳过已复制的文件。When it is started again, it will resume at the last checkpoint meaning that only the files that have already been copied are skipped.

Workflow Copy-Files
{
    $files = @("C:\LocalPath\File1.txt","C:\LocalPath\File2.txt","C:\LocalPath\File3.txt")

    ForEach ($File in $Files)
    {
        Copy-Item -Path $File -Destination \\NetworkPath
        Write-Output "$File copied."
        Checkpoint-Workflow
    }

    Write-Output "All files copied."
}

由于调用 Suspend-Workflow 活动后或在最后一个检查点之后,将不保留用户名凭据,所以需要在调用 Suspend-Workflow 或检查点后将凭据设置为 null,然后再从资产存储重新检索凭据。Because username credentials are not persisted after you call the Suspend-Workflow activity or after the last checkpoint, you need to set the credentials to null and then retrieve them again from the asset store after Suspend-Workflow or checkpoint is called. 否则,可能会收到以下错误消息:无法继续执行工作流作业,因为无法完整保存持久性数据或保存的持久性数据已损坏。必须重启工作流。Otherwise, you may receive the following error message: The workflow job cannot be resumed, either because persistence data could not be saved completely, or saved persistence data has been corrupted. You must restart the workflow.

下面的相同代码演示如何在 PowerShell 工作流 Runbook 中处理此问题。The following same code demonstrates how to handle this in your PowerShell Workflow runbooks.

workflow CreateTestVms
{
   $Cred = Get-AzureAutomationCredential -Name "MyCredential"
   $null = Add-AzureRmAccount -Credential $Cred

   $VmsToCreate = Get-AzureAutomationVariable -Name "VmsToCreate"

   foreach ($VmName in $VmsToCreate)
     {
      # Do work first to create the VM (code not shown)

      # Now add the VM
      New-AzureRmVm -VM $Vm -Location "WestUs" -ResourceGroupName "ResourceGroup01"

      # Checkpoint so that VM creation is not repeated if workflow suspends
      $Cred = $null
      Checkpoint-Workflow
      $Cred = Get-AzureAutomationCredential -Name "MyCredential"
      $null = Add-AzureRmAccount -Credential $Cred
     }
 }

此外,如果使用配置了服务主体的运行方式帐户进行身份验证,则不需要此处理。This is not required if you are authenticating using a Run As account configured with a service principal.

关于检查点的详细信息,请参阅向脚本工作流添加检查点For more information about checkpoints, see Adding Checkpoints to a Script Workflow.

后续步骤Next steps