PowerShell

Tus scripts de PowerShell, con la planificación que nunca tuvieron.

Dagu ejecuta PowerShell, pwsh y cmd.exe como pasos normales de un flujo, así que los scripts existentes mantienen su forma y ganan orden, reintentos, registros por paso e historial de ejecuciones consultable en el navegador.

PowerShell, pwsh y cmd.exe en el mismo flujo
Shell elegible por flujo o por paso
La salida de un script alimenta al siguiente
Se ejecuta como servicio de Windows
01

Elige el shell una vez, o por paso

Un flujo declara su shell y todos los pasos lo heredan. Sin declaración, Dagu prefiere PowerShell, luego pwsh y luego cmd.exe, de modo que un flujo escrito en una máquina se comporta de forma predecible en otra.

  • El shell admite una cadena o un array; la forma de array evita problemas de comillas con argumentos como -NoProfile
  • Un paso captura su salida en una variable con nombre que los pasos posteriores y las precondiciones pueden leer
  • Las precondiciones condicionan un paso a ese valor, así que el reinicio solo ocurre si el servicio está realmente detenido
Comprobar un servicio y reiniciarlo solo si hace falta
# 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 y cmd.exe en un mismo flujo

Los archivos batch heredados rara vez se reescriben solo porque cambie el planificador. Un paso puede sobrescribir el shell del flujo, de modo que un flujo mayoritariamente PowerShell siga llamando al .bat que lleva diez años funcionando.

  • La sobrescritura del shell va en with.shell; un campo shell suelto no puede combinarse con run y el validador lo rechaza
  • Para una lista de argumentos exacta sin interpretación de shell, usa un paso exec estructurado con command y args
  • Los flujos mixtos conservan una sola planificación, un solo historial y una sola vía de notificación

Las rutas de Windows contienen barras invertidas: en YAML conviene usar escalares de bloque o comillas simples. En una cadena entre comillas dobles, una barra invertida seguida de un carácter es un escape, no un separador de ruta.

PowerShell, cmd y un exec directo en un archivo
# 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

Los scripts de varias líneas siguen siendo legibles

Un paso puede contener un bloque de script completo en lugar de una sola línea, lo que mantiene tuberías y filtros en la forma en que los escribiría un autor de PowerShell.

  • Los escalares de bloque conservan los saltos de línea, así que las tuberías repartidas en varias líneas quedan intactas
  • retry_policy se aplica a todo el paso, lo que encaja con scripts que tocan rutas de red inestables o archivos en uso
  • pwsh y Windows PowerShell se eligen por nombre, así que un host con ambos ejecuta cada flujo en el previsto
Un script de archivado de registros programado
# 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

Desde dónde se ejecuta

La planificación solo sirve si el planificador está en marcha. El instalador de Windows puede registrar Dagu como servicio, de modo que los flujos arranquen con la máquina y no con una sesión iniciada.

  • El instalador de PowerShell registra un servicio de Windows mediante un envoltorio WinSW con versión fijada, verificable con Get-Service
  • Hay binarios de Windows para amd64, 386 y arm64
  • La consola web muestra el historial y la salida por paso desde cualquier navegador: revisar un trabajo no exige escritorio remoto

Windows Server 2019 y posteriores es el objetivo seguro. En versiones antiguas sin AF_UNIX los flujos siguen ejecutándose, pero el socket de estado en vivo y control de parada no está disponible y Dagu registra un aviso.

FAQ

Practical questions before adopting

¿Tengo que reescribir mis scripts como YAML?

No. El YAML describe cuándo se ejecuta un script, de qué depende y qué ocurre si falla. El script sigue siendo un archivo .ps1, invocado igual que lo hacía el Programador de tareas.

¿Cómo paso un valor de un script al siguiente?

Dale un nombre de salida al paso que lo produce y referéncialo en pasos posteriores. La misma referencia funciona en una precondición, lo que permite saltar un paso salvo que una comprobación previa devuelva cierto valor.

¿Puede un flujo usar Windows PowerShell y pwsh a la vez?

Sí. Define uno como predeterminado del flujo y sobrescribe el otro en los pasos que lo necesiten. Ambos se seleccionan por nombre de ejecutable.

¿Por qué el validador rechaza un campo shell en mi paso?

Un campo shell suelto no puede combinarse con run en el mismo paso. Coloca la sobrescritura bajo with.shell. Ejecutar dagu validate lo detecta antes de que se dispare la planificación.

¿Funciona también en Linux?

Sí. pwsh funciona en Linux y macOS, y la misma definición de flujo sirve allí. Solo son específicos de Windows los pasos que llaman a cmd.exe o a cmdlets exclusivos de Windows.

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.