PowerShell

Ihre PowerShell-Skripte, mit der Planung, die ihnen immer gefehlt hat.

Dagu führt PowerShell, pwsh und cmd.exe als gewöhnliche Workflow-Schritte aus. Bestehende Skripte behalten ihre Form und gewinnen Reihenfolge, Retries, Logs je Schritt und eine Laufhistorie im Browser.

PowerShell, pwsh und cmd.exe im selben Workflow
Shell je Workflow oder je Schritt wählbar
Ausgabe eines Skripts speist das nächste
Läuft als Windows-Dienst
01

Die Shell einmal wählen, bei Bedarf je Schritt

Ein Workflow deklariert seine Shell und alle Schritte erben sie. Ohne Angabe bevorzugt Dagu PowerShell, dann pwsh, dann cmd.exe, sodass ein auf einer Maschine geschriebener Workflow sich auf einer anderen vorhersagbar verhält.

  • Die Shell akzeptiert einen String oder ein Array; die Array-Form vermeidet Quoting-Probleme bei Argumenten wie -NoProfile
  • Ein Schritt fängt seine Ausgabe in einer benannten Variable auf, die spätere Schritte und Vorbedingungen lesen können
  • Vorbedingungen steuern einen Schritt über diesen Wert, sodass ein Neustart nur erfolgt, wenn der Dienst wirklich gestoppt ist
Dienst prüfen und nur bei Bedarf neu starten
# service-health.yaml
schedule: "*/15 * * * *"
max_active_runs: 1
shell: powershell -NoProfile

steps:
  - id: check_service
    run: |
      (Get-Service -Name 'MyAppSvc').Status
    output: SVC_STATUS

  - id: restart_if_stopped
    run: Restart-Service -Name 'MyAppSvc'
    depends: check_service
    preconditions:
      - condition: "${SVC_STATUS}"
        expected: "Stopped"
    retry_policy:
      limit: 2
      interval_sec: 30

mail_on:
  failure: true
02

PowerShell und cmd.exe in einem Workflow

Alte Batch-Dateien werden selten nur wegen eines Schedulerwechsels neu geschrieben. Ein Schritt kann die Workflow-Shell überschreiben, sodass ein überwiegend PowerShell-basierter Workflow weiterhin die seit zehn Jahren bewährte .bat aufruft.

  • Die Shell-Überschreibung gehört unter with.shell; ein bloßes shell-Feld lässt sich nicht mit run kombinieren und wird vom Validator abgelehnt
  • Für eine exakte Argumentliste ohne Shell-Interpretation dient ein strukturierter exec-Schritt mit command und args
  • Gemischte Workflows behalten einen Zeitplan, eine Historie und einen Benachrichtigungsweg, unabhängig von der Shell je Schritt

Windows-Pfade enthalten Backslashes; verwenden Sie in YAML bevorzugt Block-Skalare oder einfache Anführungszeichen. In doppelt gequoteten Strings gilt ein Backslash mit Folgezeichen als Escape und nicht als Pfadtrenner.

PowerShell, cmd und ein direkter exec in einer Datei
# maintenance.yaml
schedule: "0 3 * * *"
shell: ["powershell", "-NoProfile"]

steps:
  - id: report_disk
    run: Get-PSDrive -PSProvider FileSystem | Out-String
    output: DISK_REPORT

  - id: legacy_job
    run: |
      @echo off
      call C:\ops\legacy\run.bat
    with:
      shell: cmd
    depends: report_disk

  - id: direct_exec
    action: exec
    with:
      command: C:\Windows\System32\cmd.exe
      args:
        - /c
        - echo
        - done
    depends: legacy_job

mail_on:
  failure: true
03

Mehrzeilige Skripte bleiben lesbar

Ein Schritt kann einen ganzen Skriptblock statt einer einzelnen Zeile enthalten, sodass Pipelines und Filter in der Form bleiben, in der ein PowerShell-Autor sie schreibt.

  • Block-Skalare bewahren Zeilenumbrüche, sodass mehrzeilige Pipelines unverändert erhalten bleiben
  • retry_policy gilt für den gesamten Schritt und passt zu Skripten, die unzuverlässige Netzwerkpfade oder belegte Dateien anfassen
  • pwsh und Windows PowerShell werden über den Namen gewählt, sodass ein Host mit beiden jeden Workflow auf der gewünschten Variante ausführt
Ein Skript zur Logarchivierung nach Zeitplan
# archive-logs.yaml
schedule: "30 1 * * *"
shell: pwsh -NoProfile

steps:
  - id: archive
    run: |
      $cutoff = (Get-Date).AddDays(-30)
      Get-ChildItem -Path 'D:\logs' -Filter *.log |
        Where-Object { $_.LastWriteTime -lt $cutoff } |
        Compress-Archive -DestinationPath 'D:\archive\logs.zip' -Update
    retry_policy:
      limit: 2
      interval_sec: 60

  - id: verify
    run: Test-Path 'D:\archive\logs.zip'
    depends: archive

mail_on:
  failure: true
04

Woher es läuft

Planung nützt nur, wenn der Planer läuft. Der Windows-Installer kann Dagu als Dienst registrieren, sodass Workflows mit der Maschine starten statt mit einer angemeldeten Sitzung.

  • Der PowerShell-Installer registriert über einen versionsfixierten WinSW-Wrapper einen Windows-Dienst, prüfbar mit Get-Service
  • Windows-Builds erscheinen für amd64, 386 und arm64
  • Die Web-Konsole zeigt Laufhistorie und Ausgabe je Schritt aus jedem Browser, eine Remotedesktop-Sitzung ist zum Nachsehen nicht nötig

Windows Server 2019 und neuer ist das sichere Ziel. Auf älteren Builds ohne AF_UNIX laufen Workflows weiterhin, aber der Socket für Live-Status und Stopp-Steuerung fehlt und Dagu protokolliert eine Warnung.

FAQ

Practical questions before adopting

Muss ich meine Skripte als YAML neu schreiben?

Nein. Das YAML beschreibt, wann ein Skript läuft, wovon es abhängt und was bei einem Fehler passiert. Das Skript selbst bleibt eine .ps1-Datei und wird so aufgerufen wie zuvor durch die Aufgabenplanung.

Wie gebe ich einen Wert an das nächste Skript weiter?

Geben Sie dem erzeugenden Schritt einen Ausgabenamen und referenzieren Sie ihn in späteren Schritten. Dieselbe Referenz funktioniert in einer Vorbedingung, womit sich ein Schritt überspringen lässt, sofern eine frühere Prüfung nicht einen bestimmten Wert lieferte.

Kann ein Workflow Windows PowerShell und pwsh zugleich nutzen?

Ja. Setzen Sie eines als Standard des Workflows und überschreiben Sie das andere in den Schritten, die es brauchen. Beide werden über den Namen der ausführbaren Datei gewählt.

Warum lehnt der Validator ein shell-Feld an meinem Schritt ab?

Ein bloßes shell-Feld lässt sich nicht mit run im selben Schritt kombinieren. Legen Sie die Überschreibung stattdessen unter with.shell ab. dagu validate findet das, bevor der Zeitplan greift.

Funktioniert das auch unter Linux?

Ja. pwsh läuft unter Linux und macOS, und dieselbe Workflow-Definition funktioniert dort. Windows-spezifisch bleiben nur Schritte, die cmd.exe oder reine Windows-Cmdlets aufrufen.

Next step

Start with one workflow.

Install Dagu, move one script that runs on cron today into YAML, and decide from a real run history.