Запуск автономного фонового процесса в PowerShell

У меня есть программа Java, которую я хотел бы запустить в качестве фонового процесса из PowerShell script, аналогично тому, как демон работает в Linux. PowerShell script должен сделать несколько вещей:

  • Запустите программу как отдельный и отсоединенный процесс в фоновом режиме, то есть родительское окно может быть закрыто и процесс будет работать.
  • Перенаправить стандартный вывод программы и стандартную ошибку в файлы.
  • Сохраните PID фонового процесса в файл, чтобы его можно было завершить позже другим script.

У меня есть оболочка script в Linux, которая запускает программу следующим образом:

$ java -jar MyProgram.jar >console.out 2>console.err &

Я надеюсь повторить то же поведение в Windows, используя PowerShell script. Я попытался использовать Start-Process с различными комбинациями опций, а также с созданием объектов System.Diagnostics.ProcessStartInfo и System.Diagnostics.Process, но до сих пор мне не повезло. PowerShell запускает программу как фоновый процесс, но программа внезапно завершается, когда окно DOS, которое запустило сеанс PowerShell, закрыто. Я хотел бы, чтобы он начинался в фоновом режиме и не зависел от начального окна команды.

Перенаправление вывода также было проблематичным, так как кажется, что потоки вывода и ошибок могут быть перенаправлены только в процессе, выполняется в том же окне (например, используя -NoNewWindow).

Возможно ли это в PowerShell?

Ответ 1

Используйте jobs для этого:

Start-Job -ScriptBlock {
  & java -jar MyProgram.jar >console.out 2>console.err
}

Другой вариант: Start-Process:

Start-Process java -ArgumentList '-jar', 'MyProgram.jar' `
  -RedirectStandardOutput '.\console.out' -RedirectStandardError '.\console.err'

Ответ 2

Это старый пост, но, поскольку я работаю, он думал, что это может помочь поделиться. Его призыв к "java" вместо "javaw", вероятно, относится к вашей проблеме. Выпустил сам, используя мою программу jEdit java через powershell, чтобы запустить ее.

#Requires -Version 3.0
$MyDriveRoot = (Get-Location).Drive.Root
$JEditDir = $($mydriveroot + "jEdit") ;# Should be C:\jEdit or wherever you want. JEdit is a sub-directory.
$jEdit = $($JEditDir + "\jedit.jar" )
$jEditSettings = $($JEditDir + "\settings")
$JEditLogs = $($JEditDir + "\logs")

Start-Process -FilePath javaw -ArgumentList ( '-jar',"$jEdit", '-settings="$JEditSettings"' ) -RedirectStandardOutput "$JEditLogs\console.out" -RedirectStandardError "$JEditLogs\console.err"

Что вы можете превратить в небольшую функцию, а затем в псевдоним, чтобы он легко запускался в Powershell.

If ( ( Test-Path $jedit) ) {
    Function Start-JEdit() {
        Start-Process -FilePath javaw -ArgumentList ( '-jar',"$jEdit", '-settings="$($mydriveroot + "jEdit\settings")"' ) -RedirectStandardOutput "$JEditLogs\console.out" -RedirectStandardError "$JEditLogs\console.err"
    }
New-Alias -Name jedit  -Force Start-JEdit  -Description "Start JEdit programmers text editor" 
}

Ответ 3

Подумайте о том, как использовать этот планировщик задач. Определите задачу и установите ее без каких-либо триггеров. Это позволит вам просто запустить "запустить" (вручную запустить) задачу.

Вы можете настроить и/или запустить запланированные задачи с помощью модуля powershell ScheduledTasks, или вы можете использовать графический интерфейс.