在PowerShell中启动分离的后台进程

时间:2021-01-31 19:16:49

I have a Java program which I would like to launch as a background process from a PowerShell script, similar to the way a daemon runs on Linux. The PowerShell script needs to do a couple of things:

我有一个Java程序,我想从PowerShell脚本作为后台进程启动,类似于守护程序在Linux上运行的方式。 PowerShell脚本需要执行以下操作:

  1. Run the program as a separate and detached process in the background, meaning the parent window can be closed and the process keeps running.
  2. 在后台运行程序作为单独的分离进程,这意味着可以关闭父窗口并继续运行该进程。
  3. Redirect the program's standard output and standard error to files.
  4. 将程序的标准输出和标准错误重定向到文件。
  5. Save the PID of the background process to a file so it can be terminated later by another script.
  6. 将后台进程的PID保存到文件中,以便稍后由另一个脚本终止。

I have a shell script on Linux which starts the program like so:

我在Linux上有一个shell脚本,它启动程序如下:

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

I'm hoping to replicate the same behavior on Windows using a PowerShell script. I have tried using Start-Process with various combinations of options, as well as creating System.Diagnostics.ProcessStartInfo and System.Diagnostics.Process objects, but so far I am not having any luck. PowerShell starts the program as a background process, but the program abruptly terminates when the DOS window which started the PowerShell session is closed. I would like it to start in the background and be independent of the command window which started it.

我希望使用PowerShell脚本在Windows上复制相同的行为。我尝试使用Start-Process和各种选项组合,以及创建System.Diagnostics.ProcessStartInfo和System.Diagnostics.Process对象,但到目前为止我没有任何运气。 PowerShell作为后台进程启动程序,但是当启动PowerShell会话的DOS窗口关闭时,程序突然终止。我希望它在后台启动并独立于启动它的命令窗口。

The output redirection has also been troublesome, as it seems that the output and error streams can only be redirected in the process is being run in the same window (e.g., using -NoNewWindow).

输出重定向也很麻烦,因为似乎输出和错误流只能在同一窗口中运行的过程中重定向(例如,使用-NoNewWindow)。

Is this sort of thing possible in PowerShell?

在PowerShell中这种事情是否可行?

3 个解决方案

#1


14  

Use jobs for this:

使用作业:

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

Another option would be Start-Process:

另一个选择是Start-Process:

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

#2


2  

Consider using the task scheduler for this. Define a task and set it without any triggers. That will allow you to simply "Run" (manually trigger) the task.

考虑使用任务调度程序。定义任务并设置它而不需要任何触发器。这将允许您简单地“运行”(手动触发)任务。

You can set up and/or trigger scheduled tasks using the ScheduledTasks powershell module, or you can use the GUI.

您可以使用ScheduledTasks powershell模块设置和/或触发计划任务,也可以使用GUI。

#3


2  

This is an old post but since I have it working fine thought it might help to share. Its the call to 'java' instead of 'javaw' that is likely your issue. Ran it out myself using my JEdit java program through powershell to launch it.

这是一个古老的帖子,但是因为我认为它工作得很好,所以可能有助于分享。它是对'java'而不是'javaw'的调用,这可能是你的问题。通过powershell使用我的JEdit java程序来启动它。

#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"

Which you can turn into a little function and then an alias to make it easy to launch in Powershell.

您可以将其转换为一个小功能,然后使用别名,以便在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" 
}

#1


14  

Use jobs for this:

使用作业:

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

Another option would be Start-Process:

另一个选择是Start-Process:

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

#2


2  

Consider using the task scheduler for this. Define a task and set it without any triggers. That will allow you to simply "Run" (manually trigger) the task.

考虑使用任务调度程序。定义任务并设置它而不需要任何触发器。这将允许您简单地“运行”(手动触发)任务。

You can set up and/or trigger scheduled tasks using the ScheduledTasks powershell module, or you can use the GUI.

您可以使用ScheduledTasks powershell模块设置和/或触发计划任务,也可以使用GUI。

#3


2  

This is an old post but since I have it working fine thought it might help to share. Its the call to 'java' instead of 'javaw' that is likely your issue. Ran it out myself using my JEdit java program through powershell to launch it.

这是一个古老的帖子,但是因为我认为它工作得很好,所以可能有助于分享。它是对'java'而不是'javaw'的调用,这可能是你的问题。通过powershell使用我的JEdit java程序来启动它。

#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"

Which you can turn into a little function and then an alias to make it easy to launch in Powershell.

您可以将其转换为一个小功能,然后使用别名,以便在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" 
}