PowerShell

Os seus scripts PowerShell, com o agendamento que nunca tiveram.

O Dagu executa PowerShell, pwsh e cmd.exe como passos normais de um workflow, por isso os scripts existentes mantêm a forma e ganham ordem, retentativas, logs por passo e um histórico de execuções que se abre no navegador.

PowerShell, pwsh e cmd.exe no mesmo workflow
Shell escolhida por workflow ou por passo
A saída de um script alimenta o seguinte
Corre como serviço do Windows
01

Escolher a shell uma vez, ou por passo

Um workflow declara a sua shell e todos os passos a herdam. Sem declaração, o Dagu prefere PowerShell, depois pwsh, depois cmd.exe, por isso um workflow escrito numa máquina comporta-se de forma previsível noutra.

  • A shell aceita uma string ou um array; a forma de array evita problemas de aspas com argumentos como -NoProfile
  • Um passo captura a sua saída numa variável nomeada que passos seguintes e pré-condições conseguem ler
  • As pré-condições condicionam um passo a esse valor, por isso o reinício só acontece se o serviço estiver mesmo parado
Verificar um serviço e reiniciá-lo só se for preciso
# 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 e cmd.exe no mesmo workflow

Ficheiros batch antigos raramente são reescritos só porque o agendador mudou. Um passo pode sobrepor a shell do workflow, de modo que um workflow maioritariamente PowerShell continue a chamar o .bat que funciona há dez anos.

  • A sobreposição da shell vai em with.shell; um campo shell isolado não pode ser combinado com run e o validador rejeita-o
  • Para uma lista de argumentos exata sem interpretação de shell, use um passo exec estruturado com command e args
  • Workflows mistos mantêm um agendamento, um histórico e um caminho de notificação únicos

Os caminhos do Windows contêm barras invertidas; em YAML prefira escalares de bloco ou plicas. Numa string entre aspas duplas, uma barra invertida seguida de um carácter é uma sequência de escape e não um separador de caminho.

PowerShell, cmd e um exec direto num ficheiro
# 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

Scripts de várias linhas continuam legíveis

Um passo pode conter um bloco de script completo em vez de uma única linha, mantendo pipelines e filtros na forma em que um autor de PowerShell os escreveria.

  • Escalares de bloco preservam as quebras de linha, por isso pipelines repartidos por várias linhas ficam intactos
  • retry_policy aplica-se ao passo inteiro, o que serve scripts que tocam caminhos de rede instáveis ou ficheiros ocupados
  • pwsh e Windows PowerShell são escolhidos pelo nome, por isso um host com ambos executa cada workflow no pretendido
Um script de arquivo de logs agendado
# 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

De onde corre

O agendamento só serve se o agendador estiver a correr. O instalador do Windows pode registar o Dagu como serviço, para que os workflows arranquem com a máquina e não com uma sessão iniciada.

  • O instalador PowerShell regista um serviço do Windows através de um wrapper WinSW com versão fixada, verificável com Get-Service
  • São publicados binários Windows para amd64, 386 e arm64
  • A consola web mostra o histórico e a saída por passo a partir de qualquer navegador, sem precisar de ambiente de trabalho remoto

Windows Server 2019 e posterior é o alvo seguro. Em versões mais antigas sem AF_UNIX os workflows continuam a correr, mas o socket de estado em direto e de controlo de paragem fica indisponível e o Dagu regista um aviso.

FAQ

Practical questions before adopting

Tenho de reescrever os meus scripts em YAML?

Não. O YAML descreve quando um script corre, de que depende e o que acontece quando falha. O script continua a ser um ficheiro .ps1, chamado tal como o Agendador de Tarefas o chamava.

Como passo um valor de um script para o seguinte?

Dê um nome de saída ao passo que o produz e referencie-o nos passos seguintes. A mesma referência funciona numa pré-condição, o que permite saltar um passo a menos que uma verificação anterior devolva determinado valor.

Um único workflow pode usar Windows PowerShell e pwsh?

Pode. Defina um como predefinição do workflow e sobreponha o outro nos passos que o exijam. Ambos são selecionados pelo nome do executável.

Porque é que o validador rejeita um campo shell no meu passo?

Um campo shell isolado não pode ser combinado com run no mesmo passo. Coloque a sobreposição em with.shell. Correr dagu validate deteta isto antes de o agendamento disparar.

Isto funciona também em Linux?

Funciona. O pwsh corre em Linux e macOS e a mesma definição de workflow aplica-se. Só ficam específicos do Windows os passos que chamam cmd.exe ou cmdlets exclusivos do 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.