瞭解適用于 Azure 自動化 的 PowerShell 工作流程

Azure 自動化中的 Runbook 會實作為 Windows PowerShell 工作流程、使用 Windows Workflow Foundation 的 Windows PowerShell 腳本。 工作流程是一系列經過程式設計、相互連結的步驟,能夠執行長期的工作,或是需要與多部裝置或受管理節點上的多個步驟協調進行。

雖然工作流程是以 Windows PowerShell 語法撰寫,並由 Windows PowerShell 啟動,但 Windows Workflow Foundation 會加以處理。 工作流程對於一般腳本的優點包括針對多個裝置同時執行動作的效能,以及從失敗中自動復原。

注意

本文適用于 PowerShell 5.1;PowerShell 7.1 (預覽) 和 PowerShell 7.2 (預覽) 不支援工作流程。 PowerShell 工作流程腳本與 Windows PowerShell 腳本非常類似,但有一些顯著的差異,可能會讓新使用者感到困惑。 因此,建議您只有在需要使用 檢查點 時,才使用 PowerShell 工作流程撰寫 Runbook。

如需本文中主題的完整詳細資料,請參閱 開始使用 Windows PowerShell 工作流程

使用 Workflow 關鍵字

將 PowerShell 腳本轉換成 PowerShell 工作流程的第一個步驟是使用 Workflow 關鍵字括住它。 工作流程會以 Workflow 關鍵字開頭,後面接著以大括弧括住的腳本主體。 工作流程的名稱會遵循 關鍵字, Workflow 如下列語法所示:

Workflow Test-Workflow
{
    <Commands>
}

工作流程的名稱必須符合自動化 Runbook 的名稱。 如果要匯入 Runbook,則檔案名必須符合工作流程名稱,而且必須以 .ps1 結尾。

若要將參數新增至工作流程,請使用 Param 關鍵字,就像您在腳本中一樣。

瞭解 PowerShell 工作流程程式碼與 PowerShell 腳本程式碼之間的差異

PowerShell 工作流程程式碼看起來幾乎與 PowerShell 腳本程式碼完全相同,但有一些重大變更除外。 下列各節說明您需要對 PowerShell 腳本進行變更,才能在工作流程中執行。

活動

活動是工作流程中以序列執行的特定工作。 Windows PowerShell 工作流程會自動將許多 Windows PowerShell 指令程式轉換成在工作流程中執行的活動。 當您在 Runbook 中指定其中一個 Cmdlet 時,對應的活動會由 Windows Workflow Foundation 執行。

如果 Cmdlet 沒有對應的活動,Windows PowerShell 工作流程會自動在 InlineScript 活動中執行 Cmdlet。 除非明確將它們包含在 InlineScript 區塊中,否則會排除某些 Cmdlet,且無法在工作流程中使用。 如需詳細資訊,請參閱 在腳本工作流程 中使用活動。

工作流程活動會共用一組通用參數來設定其作業。 請參閱 about_WorkflowCommonParameters

位置參數

您無法在工作流程中使用位置參數搭配活動和 Cmdlet。 因此,您必須使用參數名稱。 請考慮下列取得所有執行中服務的程式碼:

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

如果您嘗試在工作流程中執行此程式碼,您會收到類似 Parameter set cannot be resolved using the specified named parameters. 若要更正此問題的訊息,請提供參數名稱,如下列範例所示:

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

還原序列化的物件

工作流程中的物件會還原序列化,這表示其屬性仍可供使用,但不能使用其方法。 例如,請考慮下列 PowerShell 程式碼,它會使用 Stop 物件的 方法 Service 停止服務。

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

如果您嘗試在工作流程中執行此動作,您會收到錯誤指出 Method invocation is not supported in a Windows PowerShell Workflow.

其中一個選項是在 InlineScript 區塊中 包裝這兩行程式碼。 在此情況下, Service 表示 區塊內的服務物件。

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

另一個選項是使用與 方法具有相同功能的另一個 Cmdlet,如果有的話。 在我們的範例中 Stop-Service ,Cmdlet 提供與 Stop 方法相同的功能,而且您可以使用下列程式碼作為工作流程。

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

使用 InlineScript

當您需要以傳統 PowerShell 腳本執行一或多個命令,而不是 PowerShell 工作流程時,此 InlineScript 活動很有用。 當工作流程中的命令傳送至 Windows Workflow Foundation 進行處理時,InlineScript 區塊中的命令則會由 Windows PowerShell 執行。

InlineScript 使用下列語法,如下所示。

InlineScript
{
    <Script Block>
} <Common Parameters>

您可以將輸出指派給變數,以傳回 InlineScript 的輸出。 下列範例會停止服務,然後輸出服務名稱。

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

    $Output.Name
}

您可以將值傳遞至 InlineScript 區塊,但必須使用 $Using 範圍修飾詞。 下列範例與上一個範例相同,不同之處在于服務名稱是由變數提供。

Workflow Stop-MyService
{
    $ServiceName = "MyService"

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

    $Output.Name
}

雖然 InlineScript 活動在某些工作流程中可能很重要,但它們不支援工作流程建構。 您應該只在需要時才使用它們,原因如下:

  • 您無法在 InlineScript 區塊內使用 檢查點 。 如果區塊內發生失敗,它必須從區塊的開頭繼續。
  • 您無法在 InlineScript 區塊內使用 平行執行
  • InlineScript 會影響工作流程的延展性,因為它會保存整個 InlineScript 區塊長度的 Windows PowerShell 會話。

如需使用 InlineScript 的詳細資訊,請參閱 在工作流程 中執行 Windows PowerShell 命令和 about_InlineScript

使用平行處理

Windows PowerShell 工作流程的其中一個優勢就是可平行執行一組命令,而不需要像一般指令碼一樣依序執行。

您可以使用 Parallel 關鍵字,建立具有多個同時執行的命令的腳本區塊。 這會使用下列語法,如下所示。 在此情況下,Activity1 和 Activity2 會同時啟動。 Activity3 只有在 Activity1 和 Activity2 都完成之後才會啟動。

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

例如,請考慮下列將多個檔案複製到網路目的地的 PowerShell 命令。 這些命令會循序執行,讓一個檔案必須在下一個檔案啟動之前完成複製。

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

下列工作流程會以平行方式執行這些相同的命令,讓它們全部同時開始複製。 只有在全部複製之後,才會顯示完成訊息。

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 建構函式同時處理集合中每個項目的命令。 集合中的項目會以平行方式執行,而指令碼區塊中的命令則會以循序方式執行。 此程式使用下列語法,如下所示。 在此情況下,Activity1 會同時針對集合中的所有專案啟動。 針對每個專案,Activity2 會在 Activity1 完成之後開始。 Activity3 只有在 Activity1 和 Activity2 都已完成所有專案之後才會啟動。 我們使用 ThrottleLimit 參數來限制平行處理原則。 太高 ThrottleLimit 可能會導致問題。 參數的理想值 ThrottleLimit 取決於您環境中的許多因素。 從低值開始,並嘗試不同的增加值,直到您找到適合您特定情況的值為止。

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

下列範例類似于先前以平行方式複製檔案的範例。 在此情況下,會針對每個檔案在複製之後顯示訊息。 只有在全部複製之後,才會顯示最終完成訊息。

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

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

    Write-Output "All files copied."
}

注意

我們不建議平行執行子 Runbook,因為已顯示這可提供不可靠的結果。 子 Runbook 的輸出有時不會顯示,而且一個子 Runbook 中的設定可能會影響其他平行子 Runbook。 、 和其他等 VerbosePreferenceWarningPreference 變數可能不會傳播至子 Runbook。 如果子 Runbook 變更這些值,在叫用之後可能無法正確還原這些值。

在工作流程中使用檢查點

檢查點是工作流程目前狀態的快照集,其中包含變數的目前值,以及產生至該點的任何輸出。 如果工作流程結束時發生錯誤或暫停,它會在下一次執行時從其最後一個檢查點開始,而不是從開頭開始。

您可以使用 活動在工作流程 Checkpoint-Workflow 中設定檢查點。 Azure 自動化具有稱為 公平共用 的功能,其中任何執行 3 小時的 Runbook 都會卸載,以允許其他 Runbook 執行。 最後,卸載的 Runbook 會重載。 如果是,它會從 Runbook 中取得的最後一個檢查點繼續執行。

若要保證 Runbook 最終完成,您必須以少於三小時的間隔新增檢查點。 如果在每次執行期間新增檢查點,而且如果 Runbook 因錯誤而收回三小時後,就會無限期地繼續 Runbook。

在下列範例中,會在 Activity2 之後發生例外狀況,導致工作流程結束。 當工作流程再次執行時,它會從執行 Activity2 開始,因為此活動就在最後一個檢查點設定之後。

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

在活動可能容易發生例外狀況的活動之後,在工作流程中設定檢查點,如果工作流程繼續,則不應該重複。 例如,您的工作流程可能會建立虛擬機器。 您可以在命令建立虛擬機器之前和之後設定檢查點。 如果建立失敗,則如果再次啟動工作流程,則會重複命令。 如果工作流程在建立成功之後失敗,在繼續工作流程時不會再次建立虛擬機器。

下列範例會將多個檔案複製到網路位置,並在每個檔案之後設定檢查點。 如果網路位置遺失,則工作流程會以錯誤結束。 再次啟動時,它會在最後一個檢查點繼續執行。 只會略過已複製的檔案。

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 活動或最後一個檢查點之後,使用者名稱認證不會保存,因此您必須將認證設定為 null,然後在呼叫 或 檢查點之後 Suspend-Workflow ,從資產存放區再次擷取認證。 否則,您可能會收到下列錯誤訊息: 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 中處理這種情況。

workflow CreateTestVms
{
    $Cred = Get-AzAutomationCredential -Name "MyCredential"
    $null = Connect-AzAccount -Credential $Cred

    $VmsToCreate = Get-AzAutomationVariable -Name "VmsToCreate"

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

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

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

注意

針對非圖形化 PowerShell Runbook, Add-AzAccountAdd-AzureRMAccount 是 連線-AzAccount 別名。 您可以使用這些 Cmdlet,或將 自動化帳戶中的模組 更新為最新版本。 即使您剛建立新的自動化帳戶,您仍可能需要更新模組。

如需檢查點的詳細資訊,請參閱 Adding Checkpoints to a Script Workflow (將檢查點新增至指令碼工作流程)

下一步