从另一个 Runbook 启动 Runbook

 

适用对象:Windows Azure Pack for Windows Server, System Center 2012 R2 Orchestrator

编写包含可以由其他 runbook 使用的离散函数的可重用、模块化 runbook 是 Service Management Automation 中的最佳做法。 父 runbook 通常调用一个或多个子 runbook 以执行所需功能。 可通过两种方法来调用子 runbook,每种方法各自具有显著差异,你应了解这些差异,以便可以确定最适合于各种不同方案的方法。

  • 使用内联执行调用子 Runbook

  • 使用 Cmdlet 启用子 Runbook

使用内联执行调用子 Runbook

要从另一个 runbook 内联调用 runbook,请使用 runbook 的名称,并完全按照使用活动或 cmdlet 的相同方式为其参数提供值。 相同 Service Management Automation 环境中的所有 runbook 都可供要采用此方法使用的所有其他 runbook 使用。 父 runbook 会等待子 runbook 完成,然后移动到下一行,并且任何输出都会直接返回给父级。

内联调用 runbook 时,它会在与父 runbook 相同的作业中运行。 子 runbook 的作业历史记录中不会存在有关其运行的指示。 来自子 runbook 的任何异常和任何流输出都会与父级关联。 这样便会使作业较少,并且可以更轻松地对它们进行跟踪和故障排除,因为子 runbook 引发的任何异常及其任何流输出都与父 runbook 的作业关联。

发布 runbook 时,它调用的任何子 runbook 都必须已具有已发布的版本。 这是因为 自动化 会在编译 runbook 时生成与所有子 runbook 的关联。 如果子 runbook 没有已发布的版本,则父 runbook 会看似发布正常,但是会在启动时生成异常。 如果发生这种情况,则可以重新发布父 runbook 以便正确引用子 runbook。 如果有任何子 runbook 更改,则无需重新发布父 runbook,因为已创建了关联。

内联调用的子 runbook 的参数可以是任何数据类型(包括复杂对象),并且不进行 JSON 序列化(使用管理门户或通过 Start-SmaRunbook cmdlet 启动 runbook 时会进行这种序列化)。

下面的示例调用一个测试子 runbook,它接受三个参数、一个复杂对象、一个整数和一个布尔值。 该子 runbook 的输出分配给一个变量。

$vm = Get-VM –Name "MyVM" –ComputerName "MyServer"
$output = Test-ChildRunbook –VM $vm –RepeatCount 2 –Restart $true

使用 Cmdlet 启用子 Runbook

可以使用 Start-SMARunbook cmdlet 启动 Runbook(如使用 Windows PowerShell 启动 Runbook 中所述)。 从 cmdlet 启动子 runbook 时,父 runbook 会在为子 runbook 创建了作业之后立即移动到下一行。 如果需要检索来自 runbook 的任何输出,则需要使用 Get-SMAJobOutput 访问作业。

使用 cmdlet 启动的子 runbook 中的作业会在与父 runbook 不同的作业中运行。 这会导致作业多于内联调用工作流时的情况,从而增加工作进程服务器上的开销,并使它们更难以进行跟踪。 不过父级可以启动多个子 runbook,而无需等待每个子级完成。 对于内联调用子 runbook 的那种相同类型的并行执行,父 runbook 需要使用并行关键字

使用 cmdlet 启动子 Runbook 的参数作为哈希表提供(如 Runbook 参数中所述)。 只能使用简单数据类型,不过可以提供凭据资产的名称(如凭据中所述)。 如果 runbook 具有复杂数据类型的参数,则它必须进行内联调用。

下面的示例启动一个具有参数的子 runbook,然后等待它完成。 一旦完成,便由父 runbook 从作业收集其输出。

$webServer = 'https://MyServer'
$port = 9090
$runbookName = "Test-Runbook"
$params = @{"VMName"="MyVM";"RepeatCount"=2;"Restart"=$true} 

$job = Start-SmaRunbook –WebServiceEndpoint $webServer –Port $port –Name $runbookName –Parameters $params

$doLoop = $true
While ($doLoop) {
   $job = Get-SmaJob –WebServiceEndpoint $webServer –Port $port -Id $job.Id
   $status = $job.Status
   $doLoop = (($status -ne "Completed") -and ($status -ne "Failed") -and ($status -ne "Suspended") -and ($status -ne "Stopped") 
}

Get-SmaJobOutput –WebServiceEndpoint $webServer –Port $port -Id $job.Id –Stream Output

用于调用子 Runbook 的方法的比较

下表总结了用于从另一个 runbook 调用 runbook 的两种方法之间的差异。

内联

Cmdlet

作业

子 runbook 在与父级相同的作业中运行。

为子 runbook 创建单独的作业。

执行

父 runbook 等待子 runbook 完成后再继续进行。

父 runbook 在启动子 runbook 之后立即继续进行。

输出

父 runbook 可以直接从子 runbook 获取输出。

父 runbook 必须从子 runbook 作业检索输出。

参数

子 runbook 参数的值单独指定,并且可以使用任何数据类型。

子 runbook 参数的值必须合并为单个哈希表,并且只能包含利用 JSON 序列化的简单、数组和对象数据类型。

发布

发布父 runbook 之前,必须先发布子 runbook。

必须在启动父 runbook 之前的任何时间先发布子 runbook。