PowerShell-werkstroom voor Azure Automation

Runbooks in Azure Automation worden geïmplementeerd als Windows PowerShell werkstromen, Windows PowerShell scripts die gebruikmaken van Windows Workflow Foundation. Een werkstroom is een opeenvolging van geprogrammeerde, met elkaar verbonden stappen waarmee langlopende taken worden uitgevoerd of die de coördinatie vereisen van meerdere stappen op meerdere apparaten of beheerde knooppunten.

Hoewel een werkstroom is geschreven met Windows PowerShell syntaxis en wordt gestart door Windows PowerShell, wordt deze verwerkt door Windows Workflow Foundation. De voordelen van een werkstroom ten opzichte van een normaal script zijn de gelijktijdige prestaties van een actie tegen meerdere apparaten en automatisch herstel na fouten.

Notitie

Dit artikel is van toepassing op PowerShell 5.1; PowerShell 7.1 (preview) en PowerShell 7.2 (preview) bieden geen ondersteuning voor werkstromen. Een PowerShell Workflow-script lijkt erg op een Windows PowerShell-script, maar heeft enkele belangrijke verschillen die verwarrend kunnen zijn voor een nieuwe gebruiker. Daarom raden we u aan om uw runbooks alleen te schrijven met behulp van PowerShell Workflow als u controlepunten moet gebruiken.

Zie Aan de slag met Windows PowerShell Workflow voor meer informatie over de onderwerpen in dit artikel.

Het trefwoord Werkstroom gebruiken

De eerste stap voor het converteren van een PowerShell-script naar een PowerShell-werkstroom is het insluiten van het Workflow trefwoord. Een werkstroom begint met het Workflow trefwoord, gevolgd door de hoofdtekst van het script tussen accolades. De naam van de werkstroom volgt het Workflow trefwoord zoals weergegeven in de volgende syntaxis:

Workflow Test-Workflow
{
    <Commands>
}

De naam van de werkstroom moet overeenkomen met de naam van het Automation-runbook. Als het runbook wordt geïmporteerd, moet de bestandsnaam overeenkomen met de naam van de werkstroom en eindigen op .ps1.

Als u parameters wilt toevoegen aan de werkstroom, gebruikt u het Param trefwoord op dezelfde wijze als in een script.

Meer informatie over verschillen tussen PowerShell Workflow-code en PowerShell-scriptcode

PowerShell Workflow-code ziet er bijna identiek uit als PowerShell-scriptcode, met uitzondering van enkele belangrijke wijzigingen. In de volgende secties worden de wijzigingen beschreven die u moet aanbrengen in een PowerShell-script om het in een werkstroom uit te voeren.

Activiteiten

Een activiteit is een specifieke taak in een werkstroom die in een reeks wordt uitgevoerd. Windows PowerShell-werkstroom converteert automatisch veel van de Windows PowerShell cmdlets in activiteiten wanneer het een werkstroom uitvoert. Wanneer u een van deze cmdlets opgeeft in uw runbook, wordt de bijbehorende activiteit uitgevoerd door Windows Workflow Foundation.

Als een cmdlet geen bijbehorende activiteit heeft, voert Windows PowerShell Workflow de cmdlet automatisch uit in een InlineScript-activiteit. Sommige cmdlets zijn uitgesloten en kunnen niet worden gebruikt in een werkstroom, tenzij u ze expliciet opneemt in een InlineScript-blok. Zie Activiteiten gebruiken in scriptwerkstromen voor meer informatie.

Werkstroomactiviteiten delen een aantal gemeenschappelijke parameters om hun werking te configureren. Zie about_WorkflowCommonParameters.

Positionele parameters

U kunt geen positionele parameters gebruiken met activiteiten en cmdlets in een werkstroom. Daarom moet u parameternamen gebruiken. Bekijk de volgende code waarmee alle actieve services worden ophaalt:

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

Als u deze code probeert uit te voeren in een werkstroom, ontvangt u een bericht zoals Parameter set cannot be resolved using the specified named parameters. Om dit probleem op te lossen, geeft u de parameternaam op, zoals in het volgende voorbeeld:

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

Gedeserialiseerde objecten

Objecten in werkstromen worden gedeserialiseerd, wat betekent dat hun eigenschappen nog steeds beschikbaar zijn, maar niet hun methoden. Neem bijvoorbeeld de volgende PowerShell-code, waarmee een service wordt gestopt met behulp van de Stop methode van het Service -object.

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

Als u dit probeert uit te voeren in een werkstroom, krijgt u een foutbericht met de melding Method invocation is not supported in a Windows PowerShell Workflow.

Eén optie is om deze twee regels code in een InlineScript-blok te verpakken. In dit geval Service vertegenwoordigt een serviceobject in het blok.

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

Een andere optie is om een andere cmdlet te gebruiken die dezelfde functionaliteit heeft als de methode, indien beschikbaar. In ons voorbeeld biedt de Stop-Service cmdlet dezelfde functionaliteit als de Stop methode en kunt u de volgende code gebruiken voor een werkstroom.

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

InlineScript gebruiken

DeInlineScript activiteit is handig wanneer u een of meer opdrachten moet uitvoeren als traditioneel PowerShell-script in plaats van als PowerShell-werkstroom. Waar opdrachten in een werkstroom naar Windows Workflow Foundation worden verzonden voor verwerking, worden opdrachten in een InlineScript blok verwerkt door Windows PowerShell.

InlineScript gebruikt de volgende syntaxis die hieronder wordt weergegeven.

InlineScript
{
    <Script Block>
} <Common Parameters>

U kunt uitvoer van een InlineScript retourneren door de uitvoer toe te wijzen aan een variabele. In het volgende voorbeeld wordt een service gestopt en wordt vervolgens de servicenaam uitgevoerd.

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

    $Output.Name
}

U kunt waarden doorgeven aan een InlineScript-blok, maar u moet $Using bereikaanpassing gebruiken. Het volgende voorbeeld is identiek aan het vorige voorbeeld, behalve dat de servicenaam wordt geleverd door een variabele.

Workflow Stop-MyService
{
    $ServiceName = "MyService"

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

    $Output.Name
}

Hoewel InlineScript-activiteiten mogelijk essentieel zijn in bepaalde werkstromen, bieden ze geen ondersteuning voor werkstroomconstructies. Gebruik ze alleen wanneer dat nodig is om de volgende redenen:

  • U kunt geen controlepunten in een InlineScript-blok gebruiken. Als er een fout optreedt binnen het blok, moet deze worden hervat vanaf het begin van het blok.
  • U kunt parallelle uitvoering niet gebruiken binnen een InlineScript-blok.
  • InlineScript is van invloed op de schaalbaarheid van de werkstroom, omdat deze de Windows PowerShell-sessie bevat voor de hele lengte van het InlineScript-blok.

Zie Windows PowerShell-opdrachten uitvoeren in een werkstroom en about_InlineScript voor meer informatie over het gebruik van InlineScript.

Parallelle verwerking gebruiken

Een voordeel van Windows PowerShell-werkstromen is de mogelijkheid om een ​​reeks opdrachten parallel uit te voeren in plaats van opeenvolgend zoals bij een typische script.

U kunt het Parallel trefwoord gebruiken om een scriptblok te maken met meerdere opdrachten die gelijktijdig worden uitgevoerd. Hiervoor wordt de volgende syntaxis gebruikt die hieronder wordt weergegeven. In dit geval starten Activiteit1 en Activiteit2 tegelijkertijd. Activiteit3 wordt pas gestart nadat zowel Activity1 als Activity2 zijn voltooid.

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

Neem bijvoorbeeld de volgende PowerShell-opdrachten waarmee meerdere bestanden naar een netwerkbestemming worden gekopieerd. Deze opdrachten worden opeenvolgend uitgevoerd, zodat het kopiëren van het ene bestand moet worden voltooid voordat het volgende wordt gestart.

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

In de volgende werkstroom worden dezelfde opdrachten parallel uitgevoerd, zodat ze allemaal tegelijkertijd beginnen met kopiëren. Pas nadat ze allemaal zijn gekopieerd, wordt het voltooiingsbericht weergegeven.

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."
}

U kunt de ForEach -Parallel constructie gebruiken om opdrachten voor elk item in een verzameling gelijktijdig te verwerken. De items in de verzameling worden parallel verwerkt, terwijl de opdrachten in het scriptblok sequentieel worden uitgevoerd. Voor dit proces wordt de volgende syntaxis gebruikt die hieronder wordt weergegeven. In dit geval begint Activiteit1 op hetzelfde moment voor alle items in de verzameling. Voor elk item begint Activiteit2 nadat Activiteit1 is voltooid. Activiteit3 start pas nadat zowel Activiteit1 als Activiteit2 voor alle items zijn voltooid. We gebruiken de ThrottleLimit parameter om de parallelle uitvoering te beperken. Te hoog van een ThrottleLimit kan problemen veroorzaken. De ideale waarde voor de ThrottleLimit parameter is afhankelijk van veel factoren in uw omgeving. Begin met een lage waarde en probeer verschillende oplopende waarden totdat u een waarde hebt gevonden die geschikt is voor uw specifieke situatie.

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

Het volgende voorbeeld is vergelijkbaar met het vorige voorbeeld waarbij bestanden parallel worden gekopieerd. In dit geval wordt voor elk bestand een bericht weergegeven nadat het is gekopieerd. Pas nadat ze allemaal zijn gekopieerd, wordt het laatste voltooiingsbericht weergegeven.

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."
}

Notitie

Het wordt afgeraden onderliggende runbooks parallel uit te voeren, omdat is aangetoond dat dit onbetrouwbare resultaten oplevert. De uitvoer van het onderliggende runbook wordt soms niet weergegeven en instellingen in het ene onderliggende runbook kunnen van invloed zijn op de andere parallelle onderliggende runbooks. Variabelen zoals VerbosePreference, WarningPreferenceen andere worden mogelijk niet doorgegeven aan de onderliggende runbooks. En als het onderliggende runbook deze waarden wijzigt, worden ze mogelijk niet goed hersteld na het aanroepen.

Controlepunten gebruiken in een werkstroom

Een controlepunt is een momentopname van de huidige status van de werkstroom met de huidige waarden voor variabelen en eventuele uitvoer die tot dat punt is gegenereerd. Als een werkstroom met een fout eindigt of wordt onderbroken, begint deze vanaf het laatste controlepunt wanneer deze de volgende keer wordt uitgevoerd, in plaats van bij het begin.

U kunt een controlepunt instellen in een werkstroom met de Checkpoint-Workflow activiteit. Azure Automation heeft een functie met de naam fair share, waarvoor elk runbook dat drie uur wordt uitgevoerd, wordt uitgeladen zodat andere runbooks kunnen worden uitgevoerd. Uiteindelijk wordt het niet-geladen runbook opnieuw geladen. Wanneer dat zo is, wordt de uitvoering hervat vanaf het laatste controlepunt dat in het runbook is genomen.

Om ervoor te zorgen dat het runbook uiteindelijk wordt voltooid, moet u controlepunten toevoegen met intervallen die minder dan drie uur worden uitgevoerd. Als tijdens elke uitvoering een nieuw controlepunt wordt toegevoegd en als het runbook na drie uur wordt verwijderd vanwege een fout, wordt het runbook voor onbepaalde tijd hervat.

In het volgende voorbeeld treedt er een uitzondering op na Activiteit2, waardoor de werkstroom wordt beëindigd. Wanneer de werkstroom opnieuw wordt uitgevoerd, wordt Activiteit2 uitgevoerd, omdat deze activiteit zich net na de laatste controlepuntenset bevond.

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

Stel controlepunten in een werkstroom in na activiteiten die vatbaar zijn voor uitzonderingen en die niet mogen worden herhaald als de werkstroom wordt hervat. Uw werkstroom kan bijvoorbeeld een virtuele machine maken. U kunt een controlepunt instellen voor en na de opdrachten om de virtuele machine te maken. Als het maken mislukt, worden de opdrachten herhaald als de werkstroom opnieuw wordt gestart. Als de werkstroom mislukt nadat het maken is voltooid, wordt de virtuele machine niet opnieuw gemaakt wanneer de werkstroom wordt hervat.

In het volgende voorbeeld worden meerdere bestanden naar een netwerklocatie gekopieerd en wordt na elk bestand een controlepunt ingesteld. Als de netwerklocatie verloren gaat, eindigt de werkstroom met een fout. Wanneer het opnieuw wordt gestart, wordt deze hervat bij het laatste controlepunt. Alleen de bestanden die al zijn gekopieerd, worden overgeslagen.

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."
}

Omdat gebruikersnaamreferenties niet worden bewaard nadat u de activiteit Suspend-Workflow hebt aangeroepen of na het laatste controlepunt, moet u de referenties instellen op null en ze vervolgens opnieuw ophalen uit het activaarchief nadat Suspend-Workflow of het controlepunt is aangeroepen. Anders kan het volgende foutbericht worden weergegeven: 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.

De volgende code laat zien hoe u met deze situatie omgaat in uw PowerShell Workflow-runbooks.

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
        }
}

Notitie

Voor niet-grafische PowerShell-runbooks Add-AzAccount en Add-AzureRMAccount zijn aliassen voor Connect-AzAccount. U kunt deze cmdlets gebruiken of u kunt uw modules bijwerken naar de nieuwste versie in uw Automation-account. Zelfs wanneer u juist een nieuw Automation-account heeft aangemaakt, moet u mogelijk uw modules bijwerken. Het gebruik van deze cmdlets is niet vereist als u verificatie uitvoert met een Uitvoeren als-account dat is geconfigureerd met een service-principal.

Zie Controlepunten toevoegen aan een scriptwerkstroom voor meer informatie over controlepunten.

Volgende stappen