How do I detach a process from Terminal, entirely?
Solution 1
First of all; once you've started a process, you can background it by first stopping it (hit Ctrl-Z) and then typing bg
to let it resume in the background. It's now a "job", and its stdout
/stderr
/stdin
are still connected to your terminal.
You can start a process as backgrounded immediately by appending a "&" to the end of it:
firefox &
To run it in the background silenced, use this:
firefox </dev/null &>/dev/null &
Some additional info:
nohup
is a program you can use to run your application with such that its stdout/stderr can be sent to a file instead and such that closing the parent script won't SIGHUP the child. However, you need to have had the foresight to have used it before you started the application. Because of the way nohup
works, you can't just apply it to a running process.
disown
is a bash builtin that removes a shell job from the shell's job list. What this basically means is that you can't use fg
, bg
on it anymore, but more importantly, when you close your shell it won't hang or send a SIGHUP
to that child anymore. Unlike nohup
, disown
is used after the process has been launched and backgrounded.
What you can't do, is change the stdout/stderr/stdin of a process after having launched it. At least not from the shell. If you launch your process and tell it that its stdout is your terminal (which is what you do by default), then that process is configured to output to your terminal. Your shell has no business with the processes' FD setup, that's purely something the process itself manages. The process itself can decide whether to close its stdout/stderr/stdin or not, but you can't use your shell to force it to do so.
To manage a background process' output, you have plenty of options from scripts, "nohup" probably being the first to come to mind. But for interactive processes you start but forgot to silence (firefox < /dev/null &>/dev/null &
) you can't do much, really.
I recommend you get GNU screen
. With screen you can just close your running shell when the process' output becomes a bother and open a new one (^Ac
).
Oh, and by the way, don't use "$@
" where you're using it.
$@
means, $1
, $2
, $3
..., which would turn your command into:
gnome-terminal -e "vim $1" "$2" "$3" ...
That's probably not what you want because -e only takes one argument. Use $1
to show that your script can only handle one argument.
It's really difficult to get multiple arguments working properly in the scenario that you gave (with the gnome-terminal -e
) because -e
takes only one argument, which is a shell command string. You'd have to encode your arguments into one. The best and most robust, but rather cludgy, way is like so:
gnome-terminal -e "vim $(printf "%q " "$@")"
Solution 2
nohup cmd &
nohup
detaches the process completely (daemonizes it)
Solution 3
If you are using bash
, try disown [jobspec]
;
see bash(1).
Another approach you can try is at now
.
If you're not superuser, your permission to use at
may be restricted.
Solution 4
Reading these answers, I was under the initial impression that issuing nohup <command> &
would be sufficient. Running zsh in gnome-terminal, I found that nohup <command> &
did not prevent my shell from killing child processes on exit. Although nohup
is useful, especially with non-interactive shells, it only guarantees this behavior if the child process does not reset its handler for the SIGHUP
signal.
In my case, nohup
should have prevented hangup signals from reaching the application, but the child application (VMWare Player in this case) was resetting its SIGHUP
handler. As a result when the terminal emulator exits, it could still kill your subprocesses. This can only be resolved, to my knowledge, by ensuring that the process is removed from the shell's jobs table. If nohup
is overridden with a shell builtin, as is sometimes the case, this may be sufficient, however, in the event that it is not...
disown
is a shell builtin in bash
, zsh
, and ksh93
,
<command> &
disown
or
<command> &; disown
if you prefer one-liners. This has the generally desirable effect of removing the subprocess from the jobs table. This allows you to exit the terminal emulator without accidentally signaling the child process at all. No matter what the SIGHUP
handler looks like, this should not kill your child process.
After the disown, the process is still a child of your terminal emulator (play with pstree
if you want to watch this in action), but after the terminal emulator exits, you should see it attached to the init process. In other words, everything is as it should be, and as you presumably want it to be.
What to do if your shell does not support disown
? I'd strongly advocate switching to one that does, but in the absence of that option, you have a few choices.
screen
andtmux
can solve this problem, but they are much heavier weight solutions, and I dislike having to run them for such a simple task. They are much more suitable for situations in which you want to maintain a tty, typically on a remote machine.- For many users, it may be desirable to see if your shell supports a capability like zsh's
setopt nohup
. This can be used to specify thatSIGHUP
should not be sent to the jobs in the jobs table when the shell exits. You can either apply this just before exiting the shell, or add it to shell configuration like~/.zshrc
if you always want it on. - Find a way to edit the jobs table. I couldn't find a way to do this in
tcsh
orcsh
, which is somewhat disturbing. - Write a small C program to fork off and
exec()
. This is a very poor solution, but the source should only consist of a couple dozen lines. You can then pass commands as commandline arguments to the C program, and thus avoid a process specific entry in the jobs table.
Solution 5
nohup $COMMAND &
$COMMAND & disown
setsid command
I've been using number 2 for a very long time, but number 3 works just as well. Also, disown
has a nohup
flag of -h
, can disown all processes with -a
, and can disown all running processes with -ar
.
Silencing is accomplished by $COMMAND &>/dev/null
.
Hope this helps!
Related videos on Youtube
slhck
Updated on September 17, 2022Comments
-
slhck over 1 year
I use Tilda (drop-down terminal) on Ubuntu as my "command central" - pretty much the way others might use GNOME Do, Quicksilver or Launchy.
However, I'm struggling with how to completely detach a process (e.g. Firefox) from the terminal it's been launched from - i.e. prevent that such a (non-)child process
- is terminated when closing the originating terminal
- "pollutes" the originating terminal via STDOUT/STDERR
For example, in order to start Vim in a "proper" terminal window, I have tried a simple script like the following:
exec gnome-terminal -e "vim $@" &> /dev/null &
However, that still causes pollution (also, passing a file name doesn't seem to work).
-
Admin about 15 yearsThat, too, is a good question. I think it's fair to consider Bash a programming language - although indeed the scope of this question is probably more on the sysadmin side...
-
Dana the Sane about 15 yearsThis is a duplicate of this question stackoverflow.com/questions/285015/…
-
behrooz about 13 years
-
jiggunjer over 7 yearsYour use case does not describe complete detachment, per se.
-
Admin about 15 years"disown" don't seem to be an internal bash command (not available on my machine, and I use bash). "nohup", as Ben suggested, might be a much better (and standard) way of doing this.
-
Admin about 15 yearsI could swear I had tried nohup before using exec - but apparently not properly, as it does work like this: nohup gnome-terminal -e "vim $@" &> /dev/null &
-
Admin about 15 yearsThanks a lot for this! Sadly I can only accept one answer. I ended up with "nohup $@ &> /dev/null &" and "alias wvim='launch.sh gnome-terminal -x vim'"
-
Ninsuo about 11 years
at
to delegate execution to someone else, I like it! +1 -
lmat - Reinstate Monica almost 11 yearsAlthough succinct is valuable, completeness is more valuable. Although nohup is a GNU coreutil, a bash-only answer (or note about there not being one) would be appropriate here. Good answer nonetheless.
-
Ron E over 10 yearsThis is exactly what I needed. I was attempting to add a console shortcut for sublime text and it works perfectly, here's what I ended up with: ("/opt/Sublime Text 2/sublime_text" $@)&
-
E Mahaso almost 10 yearsAs a point of reference, this works in
zsh
as well. -
vyom over 9 years
at now
Fantastic! -
Hi-Angel over 9 yearsStrange: when I am did «Ctrl-z» in terminal, and next «bg», the process should not anymore relying on terminal. But when I closed the terminal, it was closed too o.O
-
lhunath over 9 years@Hi-Angel when you close an interactive bash shell, bash HUPs all active jobs. When you ^Z and bg a process it is still a job, be it a background one. To remove it as a job, use
disown
, then the process will keep on living after you close the shell since bash won't HUP it anymore. -
sjas over 9 yearsWon't using
$*
instead of$@
fix the problem of the separate strings already? -
lhunath over 9 years@sjas No! That would make you inject literal data into shell code! It will result in bugs of all sorts depending on what the arguments were and could have destructive effects (never mind that creating arbitrary code execution is very unsafe)
-
nemo about 9 years
nohup
just ignores theSIGHUP
signal. It executes the process normally. No daemonization. -
Noldorin about 8 years@nemo Which means the process is not detached, but would become detached (and a child of
init
) if the shell exited... right? -
nemo about 8 years@Noldorin Yes. Ignoring SIGHUP, which is sent when the shell terminates, will leave the child process running and being relocated to init.
-
Sergiy Kolodyazhnyy over 7 yearsI am slightly confused as to why this answer uses one function wrapped into another, when its sufficient to just use one function with body like this:
( "$@" & disown) &> /dev/null
. It also makes not much sense to use1>
and2>
, because you're usingdisown
, which means you are using bash, and in bash you can just easily do&>
to redirect both stdout and stderr -
mic_e over 7 yearsI have it as two functions because (1) I think it's easier to read this way, and (2) I need the
run_disowned
functionality in other places in my dotfiles. You're right about the&>
thing, of course. -
jiggunjer over 7 years@nemo nohup also silences standard in/outs. Follow up with disown to completely detach.
-
Kyle Strand over 7 yearsAlso,
disown
doesn't seem to have the desired effect withgnome-terminal
--disown
ed processes are still killed when the terminal exits. I'd love to know why/how. -
Stefan Seidel over 7 yearsWhat you can't do, is change the stdout/stderr/stdin of a process after having launched it. - not exactly true. Use
reptyr
for this. -
Sergio almost 7 yearsUsing a NodeJS application (versus a small and robust command like nohup) in order to control unix processes seems ... really overkill, and to be honest, rather weird. I would use monit if you need the restart functionnality.
-
haccks almost 7 years@Sergio it's your choice to use depricated application.
-
Sergio almost 7 yearsSeveral releases have been made this year (one 4 days ago), so i don't see how/why you may think monit is a deprecated application. @see mmonit.com/monit/changes
-
haccks almost 7 yearsI was talking about nohup.
-
Sergio almost 7 years
nohup
is a plain standard POSIX command, so same remark : no way it is deprecated. @see unix.com/man-page/posix/1p/nohup -
Evi1M4chine over 6 years
disown
is perfect! Nowadays, it’s available in every bash, and does properly what is needed. As opposed tonohup
et al, which do some more things. -
Amos about 6 years
at now
trick is clever -
Jonathan H over 5 yearsShort and sweet; thanks for this very helpful summary!
-
Mr. Minty Fresh about 5 yearsI can't believe I still get notifications for this post...
-
aemonge almost 5 years
disown
might help too -
Suhayb almost 5 yearsAccording to bash man page,
&>>/dev/null
is sufficient to redirect stderr and stdout. i.e:firefox &>>/dev/null
-
Guillermo Prandi over 4 yearsIn Linux nohup is not enough to disassociate the process from the terminal. Programs list ssh will still know what terminal are you from and ask you -for instance- if you want to add something to the known hosts lists. Other Unixes used to have setpgrp and other tricks to completely remove a process from the termios session.
-
Steen Schütt over 4 yearsJust to clarify: So
nohup cmd &> /dev/null &disown
would be the way to go (In case you don't want output in thenohup.out
file)? -
dsm over 4 yearsSorry about the formatting. Comments are not very good at this...
user@host$ nohup mycommand >/dev/null 2>&1 & [1] 9892 nohup: ignoring input and redirecting stderr to stdout user@host$ disown user@host$
-
xeruf almost 4 years@KyleStrand for me
disown
detaches it completely, I can terminate the terminal and the process continue. Also note that you don't need to specify ajobspec
if you only want to disown the last job. (using zsh) -
Kyle Strand over 3 years@Xerus Interesting. I believe I was running Debian 7 or 8 when I wrote that comment; I don't remember what Bash version I had. I wonder if there was a bug somewhere.
-
Tuananhcwrs over 3 yearsI quite confuse when seeing that you put setsid and nohup together. We can run setsid with -f option so it will be always running in a new process. If you don't want nohup still print out to the terminal, use your second way (can remove the part setsid away too). Anything that I don't know?
-
Annahri almost 3 yearsOn bash you can just do
&> /dev/null