PowerShell

Ваши скрипты PowerShell — с планированием, которого у них никогда не было.

Dagu выполняет PowerShell, pwsh и cmd.exe как обычные шаги рабочего процесса: существующие скрипты сохраняют вид и получают порядок выполнения, повторы, логи по шагам и историю запусков, которую можно открыть в браузере.

PowerShell, pwsh и cmd.exe в одном процессе
Оболочка выбирается для процесса или шага
Вывод одного скрипта питает следующий
Работает как служба Windows
01

Выбрать оболочку один раз или для каждого шага

Рабочий процесс объявляет оболочку, и все шаги её наследуют. Без объявления Dagu предпочитает PowerShell, затем pwsh, затем cmd.exe, поэтому процесс, написанный на одной машине, ведёт себя предсказуемо на другой.

  • Оболочка задаётся строкой или массивом; форма массива снимает проблемы с кавычками для аргументов вроде -NoProfile
  • Шаг сохраняет вывод в именованную переменную, доступную последующим шагам и предусловиям
  • Предусловия управляют шагом по этому значению, поэтому перезапуск происходит, только если служба действительно остановлена
Проверить службу и перезапустить только при необходимости
# 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 и cmd.exe в одном процессе

Старые пакетные файлы редко переписывают только из-за смены планировщика. Шаг может переопределить оболочку процесса, поэтому преимущественно PowerShell-процесс по-прежнему вызывает .bat, работающий уже десять лет.

  • Переопределение оболочки указывается в with.shell; отдельное поле shell нельзя сочетать с run, валидатор его отклоняет
  • Для точного списка аргументов без разбора оболочкой используйте структурированный шаг exec с command и args
  • Смешанные процессы сохраняют одно расписание, одну историю и один путь уведомлений

Пути Windows содержат обратные слэши, поэтому в YAML лучше использовать блочные скаляры или одинарные кавычки. В строке с двойными кавычками обратный слэш с последующим символом — это escape-последовательность, а не разделитель пути.

PowerShell, cmd и прямой exec в одном файле
# 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

Многострочные скрипты остаются читаемыми

Шаг может содержать целый блок скрипта, а не одну строку, поэтому конвейеры и фильтры остаются в том виде, в каком их пишет автор на PowerShell.

  • Блочные скаляры сохраняют переносы строк, поэтому многострочные конвейеры остаются нетронутыми
  • retry_policy действует на весь шаг, что подходит скриптам, работающим с нестабильными сетевыми путями или занятыми файлами
  • pwsh и Windows PowerShell выбираются по имени, поэтому на хосте с обоими каждый процесс идёт на нужном
Скрипт архивации логов по расписанию
# 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

Откуда это работает

Расписание имеет смысл, только если планировщик запущен. Установщик для Windows может зарегистрировать Dagu как службу, чтобы процессы стартовали вместе с машиной, а не вместе с сеансом пользователя.

  • Установщик на PowerShell регистрирует службу Windows через обёртку WinSW с зафиксированной версией; проверяется через Get-Service
  • Сборки для Windows публикуются для amd64, 386 и arm64
  • Веб-консоль показывает историю запусков и вывод по шагам из любого браузера, поэтому для проверки задания не нужен удалённый рабочий стол

Безопасная цель — Windows Server 2019 и новее. На более старых сборках без AF_UNIX процессы по-прежнему выполняются, но сокет живого статуса и управления остановкой недоступен, и Dagu пишет предупреждение.

FAQ

Practical questions before adopting

Нужно ли переписывать скрипты в YAML?

Нет. YAML описывает, когда скрипт запускается, от чего зависит и что происходит при сбое. Сам скрипт остаётся файлом .ps1 и вызывается так же, как его вызывал планировщик заданий.

Как передать значение из одного скрипта в следующий?

Задайте имя вывода у шага-источника и сошлитесь на него в последующих шагах. Та же ссылка работает в предусловии, что позволяет пропускать шаг, если предыдущая проверка не вернула определённое значение.

Может ли один процесс использовать и Windows PowerShell, и pwsh?

Да. Назначьте один по умолчанию для процесса и переопределите другой на нужных шагах. Оба выбираются по имени исполняемого файла.

Почему валидатор отклоняет поле shell на шаге?

Отдельное поле shell нельзя сочетать с run в одном шаге. Поместите переопределение в with.shell. Запуск dagu validate находит это до срабатывания расписания.

Работает ли это в Linux?

Да. pwsh работает в Linux и macOS, и то же определение процесса действует там. Специфичными для Windows остаются лишь шаги, вызывающие cmd.exe или командлеты только для 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.