Creating-a-timeout-feature-in-powershell-scripts.jpg

Erstellen Einer Timeout-Funktion in einem PowerShell-Skript

Erstellen Einer Timeout-Funktion in einem PowerShell-Skript

Nur weil eines von Ihren Skripten an einer Aufgabe steckenbleibt, sollte nicht gleich Ihr ganzer Workflow stoppen. Da gibt es einen Workaround!

Haben Sie schon einmal ein PowerShell-Skript geschrieben und merken dann, dass es aus unerfindlichen Gründen immer an einer bestimmten Aufgabe hängenbleibt? Das ist ganz besonders frustrierend, wenn das Skript von einem unbeaufsichtigten Prozess angestoßen wird. Das kann den gesamten Workflow stoppen. Glücklicherweise gibt es Abhilfe. Um zu verhindern, dass ein Skript für unbestimmte Zeit hängt, kann man eine Timeout-Funktion hinzufügen. Das zwingt das Skript entweder zu enden oder weiterzuspringen, wenn eine bestimmte Aufgabe zu lange braucht.

Um eine Timeout-Funktion zu einem PowerShell-Skript hinzuzufügen, benötigt man verschiedene Aufgaben:

  • Einen Timer starten
  • Ein Stück Code aufrufen
  • Den Code-Status von Zeit zu Zeit kontrollieren
  • Wenn eine bestimmte Zeit überschritten wird, eine neue Aufgabe anfangen
  • Wenn die Zeit noch nicht überschritten ist, mit dem Skript fortfahren
  • Den Timer stoppen

Read: Advanced PowerShell Functions: Upping Your Game

Im Folgenden ein Beispiel wie dieser Prozess funktioniert:

Als erstes muss man ein Timeout definieren. In den meisten Fällen ist ein Timeout in Sekunden genügend. Mein Code soll nicht mehr als 10 Sekunden laufen, also setze ich dafür eine Variable.

$Timeout = 10 ## seconds

Als nächstes nehme ich den Code, den ich überwachen will, und füge ihn zum Skriptblock hinzu. Nehmen wir an, dass ich weiter oben im Skript einige Hintergrundjobs erstellt habe. Ich möchte warten bis alle diese Jobs fertig sind, bevor das Skript weiterläuft.

$jobs = Get-Job
$Condition = {param($jobs) 'Running' -not in $jobs.State }
$ConditionArgs = $jobs

Als nächstes muss ich definieren wie lange mein Skript zwischen den Checks die Aufgabe ausführen sollte.

$RetryInterval = 5 ## seconds

Jetzt starte ich den Timer.

## Start the timer
$timer = [Diagnostics.Stopwatch]::StartNew()

Automatisieren mit PowerShell. E-Book jetzt herunterladen >>

Wenn der Timer läuft, kann ich das Stück Code aufrufen, dass ausgeführt werden soll.

## Start checking the condition scriptblock. Do this as long as the action hasn't exceeded
## the timeout or the condition scriptblock returns something other than $false or $null.
while (($timer.Elapsed.TotalSeconds -lt $Timeout) -and (& $Condition $ConditionArgs)) {

    ## Wait a specific interval
    Start-Sleep -Seconds $RetryInterval

    ## Check the time
    $totalSecs = [math]::Round($timer.Elapsed.TotalSeconds,0)
    Write-Verbose -Message "Still waiting for action to complete after [$totalSecs] seconds..."
}

Wenn die Zeit überschritten wurde oder die Aufgabe ausgeführt wurde, muss ich den Timer stoppen.

## The action either completed or timed out. Stop the timer.
$timer.Stop()

Jetzt kann ich kontrollieren, ob die Zeit überschritten wurde oder die Aufgabe erfolgreich ausgeführt wurde. In diesem Fall benutze ich eine Ausnahme, um anzuzeigen, dass die Aktion nicht ausgeführt wurde, wenn sie durch die Timeout-Funktion gestoppt wurde. Ansonsten schreibe ich nur eine verbose-Meldung, der beliebiger Code folgen kann.

## Return status of what happened
if ($timer.Elapsed.TotalSeconds -gt $Timeout) {
    throw 'Action did not complete before timeout period.'
} else {
    Write-Verbose -Message 'Action completed before the timeout period.'
}

Eine Funktion genannt Wait-Action, die alle diese Funktionalitäten in einer PowerShell-Funktion enthält, können Sie von der PowerShell Gallery herunterladen:

Install-Script -Name Wait-Action

Tipp: Lesen Sie dazu auch das Whitepaper Automatisieren mit PowerShell oder laden Sie sich kostenfrei eine Testversion von MOVEit Automation, Software für die Automatisierung der Dateiübertragung, herunter.


Kommentare
Comments are disabled in preview mode.
Loading animation