Closed 237dmitry closed 8 months ago
@jborean93 has more in-depth knowledge in this area, but I think this comes down to platform differences:
On Windows, a Start-Process
-launched lives on independently of the PowerShell session that launched it; the only exceptions I'm aware of are:
-NoNewWindow
.Start-Process
launched processes - see #16001 for technical details.On Unix-like platforms, by contrast, a child process is by default killed if its parent is killed (loosely speaking; see @rhubarb-geek-nz's comment below for details; also, -NoNewWindow
is invariably implied, because launching a process in a new terminal window is not supported).
Start-Process nohup '...'
- see example 8 from the docs for an example call and @rhubarb-geek-nz's comment below.Going back in history, how Windows ran an EXE depended on the SUBSYSTEM of the EXE. If it was compiled with /SUBSYSTEM:CONSOLE it was considered a command line app and the command processor would wait for it to exit. If it did not have that SUBSYSTEM it was assumed to be a GUI app, and when started it was effectively detached.
Start-Process does indeed say
Example 8: Create a detached process on Linux
# Runs for 2 minutes and appends output to ./nohup.out
Start-Process nohup 'pwsh -noprofile -c "1..120 | % { Write-Host . -NoNewline; sleep 1 }"'
Unfortunately nohup
does have side effects such as appending to nohup.out
, but as the name says its role is to prevent SIGHUP from killing the process.
Thanks, @rhubarb-geek-nz (the nohup
example actually originated in the discussion in https://github.com/PowerShell/PowerShell/issues/16001).
Re Windows console-subsystem applications: What you're describing applies to direct invocation, but Start-Process
by design creates a new console window by default (as such it is the analog to cmd.exe
's built-in start
command), and in local invocations these windows are detached from the caller.
This is not a good workaround with /usr/bin/nohup
. Why rofi
, dmenu
, any launchers do start processes without nohup?
What about windows? The problem also exists.
- On Unix-like platforms, by contrast, a child process is always killed if its parent is killed
Is this true? In UNIX you may have a process group sharing a common controlling terminal. When the controlling terminal is disconnected it sends SIGHUP to all processes with that controlling terminal. The default behaviour for SIGHUP is to terminate the process, the program "nohup" breaks this connection by preventing the SIGHUP signal. Nohup does not actually remove the process from the controlling terminal
Thanks for the clarification re process groups, @rhubarb-geek-nz - I've updated the wording in my earlier comment (meant to be a summary of sorts) and added a link to yours.
@237dmitry, there is no problem on Windows that I'm aware of, except the constraints mentioned earlier: use of -NoNewWindow
and use in remoting. #16001 offers (nontrivial) workarounds for the latter, but if you feel that Start-Process
itself should support creating detached processes in remote sessions too, I suggest creating a focused feature request to that effect.
Similarly, @237dmitry, it may be worth creating a separate feature request for building the functionality of nohup
directly into Start-Process
on Unix-like platforms - either by default or via a new switch.
If you are not looking for portable code then simply use bash -c 'command... &'
$ ps
PID TTY TIME CMD
30308 pts/0 00:00:00 bash
30578 pts/0 00:00:00 ps
$ pwsh
PowerShell 7.4.1
PS> bash -c 'sleep 10 &'
PS> exit
$ ps
PID TTY TIME CMD
30308 pts/0 00:00:00 bash
30607 pts/0 00:00:00 sleep
30654 pts/0 00:00:00 ps
shows sleep is still running after powershell exit
One downside of Windows itself is the assumption that everything needs Windows and that command line programs need console windows. Often on a Windows update or an installation of an MSI you get console windows flashing up for fractions of a second, it is rather unfortunate.
here is no problem on Windows that I'm aware
Conhost window wont be closed until I press Ctrl-C
. After pressing conhost and alacritty windows close together.
simply use bash -c 'command... &'
This works like Start-Process. I'm using a script to launch a new alacritty terminal instance with different profiles (bash, pwsh, mc, htop, musikcube). There are variables and Start-Process is a more convenient way to do this. Using nohup has disadvantages, since it outputs messages to the console, and I have not yet been able to redirect them to /dev/null.
PS. I want to switch from Tilix to Alacritty.
@237dmitry, what happens on Windows is this:
alacritty.exe
is a GUI-subsystem application...--print-events
CLI option, for instance.exit
the PowerShell session while the launched Alacritty process is still alive, the latter prevents the console from closing (because Alacritty is still attached to it).The workaround is to launch via a hidden aux. console window; e.g.:
Start-Process -WindowStyle hidden cmd '/c alacrity --config %APPDATA%\alacritty\pwsh.toml'
Pragmatically speaking, you could wrap the above in an alacritty
function (which takes precedence over the external executable).
As for what should be done:
Start-Process
can or even should try to prevent this scenario.cmd.exe
sessions.@mklement0
Start-Process -WindowStyle hidden
Thank you. I'll definitely try this.
@237dmitry, as for a Unix workaround:
You can silence nohup
's console output as follows (using sleep
as a sample command to run detached, as in @rhubarb-geek-nz's demonstration) - however, there is no way I know of to prevent creation of / appending to file based on @rhubarb-geek-nz's tip, no nohup.out
nohup.out
is created / appended to, due to redirection of stdout.
sh -c '{ nohup sleep 30 & } 2>/dev/null 1>&2'
On Linux nohup only writes to nohup.out if the stdout is directed at a terminal
$ nohup sleep 1
nohup: ignoring input and appending output to 'nohup.out'
$ nohup sleep 1 > /dev/null
nohup: ignoring input and redirecting stderr to stdout
Thanks, @rhubarb-geek-nz (I just tried to see that it also applies to macOS), so the solution that prevents use of nohup.out
is (I've also updated the previous comment):
sh -c '{ nohup sleep 30 & } 2>/dev/null 1>&2'
I did not tried this yet in pwsh scripts
nohup sleep 1 0</dev/null 2>&1 1>/dev/null
@237dmitry:
From PowerShell, $null = nohup sleep 30 &
works in principle, but would require you to manually clean up the job later.
If you don't mind nohup.out
getting created, a more efficient Start-Process
-based command is:
Start-Process nohup 'sleep 30' -RedirectStandardError /dev/null
The following should work and would prevent creation of nohup.out
, but currently doesn't, due to the following bug:
Start-Process nohup 'sleep 30' -RedirectStandardOut /dev/null -RedirectStandardError /dev/null
Note: On macOS (as opposed to Linux), nohup
doesn't print a status message to stderr, so it is sufficient to redirect stdout output in order for the command to both be silent and to prevent creation of file nohup.out
:
# macOS only: prevents both console output and creation of file nohup.out
Start-Process nohup 'sleep 30' -RedirectStandardOut /dev/null
Start-Process nohup 'sleep 30' -RedirectStandardError /dev/null
Wau!!! Thank you very much!
start nohup -args "alacritty --config-file $HOME/.config/alacritty/htop.toml" -RedirectStandardError /dev/null
Works fine!
UPD. On Windows with -WindowStyle hidden
also works!
Start-Process cmd -ArgumentList "/c alacritty --title $title --config-file $config" -WindowStyle Hidden
@rhubarb-geek-nz:
Re console-subsystem applications currently invariably creating a visible console window unless attached to an existing console - which notably manifests as an inability to invoke PowerShell itself hidden, see #3028 - there's a pending PR for a Console Application Policy (now 3+ years old, most recently amended in Dec 2023), proposing a way for applications to control their console-related behavior via their manifest:
Java solved the problem by having "java.exe" and "javaw.exe", so the first one was a console app, the second was a GUI app. However you may still want stdin/stdout/stderr attached.
@rhubarb-geek-nz, an express design goal of the linked PR is to avoid the need for separate executables going forward (the python.exe
/ pythonw.exe
pair is another example).
If I understand the PR correctly, an application using the detached
policy would implicitly attach to a caller's existing console - if present.
If you use CreateProcess() with DETACHED_PROCESS it is the responsibility of the new process to call AllocConsole() if it wants a console window, rather than the parent making the assumption and using CREATE_NEW_CONSOLE. To add to the confusion there is also the CREATE_NO_WINDOW flag which is mutually exclusive with the previously mentioned flags.
According to the linked PR, it's not the parent process making the decision as to whether to allocate a console for a console-subsystem executable: it is the kernel ("every application that is stamped with the IMAGE_SUBSYSTEM_WINDOWS_CUI subsystem in its PE header will be allocated a console by kernel32.")
The design goal appears to be: Via an application manifest specifying a newly introduced console-allocation policy (detached
), allow creation of executables that:
That seems very convoluted and not in the right place at all, creating console windows should have nothing to do with the kernel. In the UNIX world controlling terminals are either system configured for serial ports or pseudo-terminals are created on demand at login by either rlogind, telnetd or sshd, or created when a new terminal window is opened (eg xterm, dtterm, gnome-terminal etc).
I'm not disagreeing; Windows has a lot of historical baggage, stemming from questionable initial design choices coupled with a commitment to backward compatibility - arguably, PowerShell itself has the same affliction (and I'm saying this as someone who is a fan of the fundamentals of PowerShell).
This issue has been marked as answered and has not had any activity for 1 day. It has been closed for housekeeping purposes.
📣 Hey @237dmitry, how did we do? We would love to hear your feedback with the link below! 🗣️
🔗 https://aka.ms/PSRepoFeedback
Prerequisites
Steps to reproduce
This behavior occurs on Linux and Windows.
On Windows it is not always possible to reproduce, depending on the application.
No problem:
Hangs console window (conhost), killing it (Ctrl-C) kills alacritty too:
Expected behavior
Actual behavior
Error details
Environment data
Visuals
No response