Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Start a detached background process in PowerShell

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:

  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. Redirect the program's standard output and standard error to files.
  3. Save the PID of the background process to a file so it can be terminated later by another script.

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

$ 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.

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).

Is this sort of thing possible in PowerShell?

like image 220
Dave Avatar asked Jul 29 '14 19:07

Dave


People also ask

How do I run a PowerShell process in the background?

The Start-Job cmdlet starts a PowerShell background job on the local computer. A PowerShell background job runs a command without interacting with the current session. When you start a background job, a job object returns immediately, even if the job takes an extended time to finish.

How do I run a PowerShell script without displaying Windows?

I found out if you go to the Task in Task Scheduler that is running the powershell.exe script, you can click "Run whether user is logged on or not" and that will never show the powershell window when the task runs.

What can you use to start a job in PowerShell other than the start-job command?

Beginning in PowerShell 6.0, you can use the background operator ( & ) at the end of a pipeline to start a background job. For more information, see background operator. Using the background operator is functionally equivalent to using the Start-Job cmdlet in the previous example.

How do I view background jobs in PowerShell?

To get all jobs and their status use the Get-Job PowerShell cmdlet. The command gets the jobs in the current PowerShell session. The output includes a background job, a remote job and several instances of a scheduled job.


4 Answers

Use jobs for this:

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

Another option would be Start-Process:

Start-Process java -ArgumentList '-jar', 'MyProgram.jar' `
  -RedirectStandardOutput '.\console.out' -RedirectStandardError '.\console.err'
like image 86
Ansgar Wiechers Avatar answered Sep 21 '22 14:09

Ansgar Wiechers


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.

like image 21
use Avatar answered Sep 20 '22 14:09

use


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.

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

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" 
}
like image 34
Ernie M. Avatar answered Sep 18 '22 14:09

Ernie M.


The solution is to combine Start-Process with nohup:

https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.management/start-process?view=powershell-7.1#example-8--create-a-detached-process-on-linux

like image 24
Alex Sobolev Avatar answered Sep 21 '22 14:09

Alex Sobolev