Jay Taylor's notes

back to listing index

How do I detach a process from Terminal, entirely?

[web search]
Original source (superuser.com)
Tags: bash linux shell-scripting unix terminal zsh nohup ksh93 linux-terminal processes superuser.com
Clipped on: 2016-10-10

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

asked Mar 23 '09 at 11:59
AnC

migrated from stackoverflow.com Aug 21 '10 at 4:05

This question came from our site for professional and enthusiast programmers.

1 upvote
  flag
That, 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... – AnC Mar 23 '09 at 12:26
   upvote
  flag
   upvote
  flag
   upvote
  flag
Your use case does not describe complete detachment, per se. – jiggunjer Aug 25 at 17:24

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 " "$@")"
answered Mar 23 '09 at 13:18
Image (Asset 4/28) alt=
lhunath
2,399164
   upvote
  flag
Thanks 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'" – AnC Mar 23 '09 at 21:33
12 upvote
  flag
What a fantastically detailed and informative answer. +1 – Teekin Oct 19 '11 at 16:06
   upvote
  flag
Strange: 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 – Hi-Angel Oct 7 '14 at 9:07
1 upvote
  flag
@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. – lhunath Oct 8 '14 at 12:47
1 upvote
  flag
Won't using $* instead of $@ fix the problem of the separate strings already? – sjas Jan 28 '15 at 19:15
nohup cmd &

nohup detaches the process completely (daemonizes it)

answered Mar 23 '09 at 12:17
Image (Asset 5/28) alt=
dsm
1,461174
9 upvote
  flag
what a fantastically succinct answer. Bravo! – dsummersl Aug 9 '12 at 1:38
3 upvote
  flag
Although 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. – Limited Atonement Jun 6 '13 at 14:48
6 upvote
  flag
nohup just ignores the SIGHUP signal. It executes the process normally. No daemonization. – nemo Mar 4 '15 at 16:29
   upvote
  flag
@nemo Which means the process is not detached, but would become detached (and a child of init) if the shell exited... right? – Noldorin Apr 8 at 0:35
   upvote
  flag
@Noldorin Yes. Ignoring SIGHUP, which is sent when the shell terminates, will leave the child process running and being relocated to init. – nemo Apr 8 at 0:58

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.

answered Mar 23 '09 at 12:05
Image (Asset 7/28) alt=
   upvote
  flag
"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. – Eigir Mar 23 '09 at 12:08
1 upvote
  flag
never thought of using "at", thanks for the idea! – cadrian Oct 10 '12 at 15:01
1 upvote
  flag
at to delegate execution to someone else, I like it! +1 – Ninsuo Apr 12 '13 at 19:23
1 upvote
  flag
As a point of reference, this works in zsh as well. – Coderer May 28 '14 at 11:10
   upvote
  flag
at now Fantastic! – vyom Aug 26 '14 at 13:00

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.

  1. screen and tmux 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.
  2. 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 that SIGHUP 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.
  3. Find a way to edit the jobs table. I couldn't find a way to do this in tcsh or csh, which is somewhat disturbing.
  4. 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.
answered Jan 22 '14 at 17:08
Image (Asset 8/28) alt=

I think screen might solve your problem

answered Mar 25 '09 at 1:51
dunkyp
  1. nohup $COMMAND &

  2. $COMMAND & disown

  3. 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!

answered Aug 25 '15 at 14:39
Image (Asset 9/28) alt=
   upvote
  flag
+1 for setsid, thanks – Zermingore Sep 23 at 8:32

in tcsh (and maybe in other shells as well), you can use parentheses to detach the process.

Compare this:

> jobs # shows nothing
> firefox &
> jobs
[1]  + Running                       firefox

To this:

> jobs # shows nothing
> (firefox &)
> jobs # still shows nothing
>

This removes firefox from the jobs listing, but it is still tied to the terminal; if you logged in to this node via 'ssh', trying to log out will still hang the ssh process.

answered Mar 23 '09 at 14:55
Image (Asset 11/28) alt=
Nathan Fellman
4,49694673

You can run your command using the nohup command, this detach your process and redirects outputs to a given file... but I am not sure that is exactly what you need ..

answered Mar 23 '09 at 12:03
Image (Asset 12/28) alt=
Ben
1494
   upvote
  flag
I 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 & – AnC Mar 23 '09 at 12:30

To disassociate tty shell run command through sub-shell for e.g.

(command)&

When exit used terminal closed but process is still alive.

check -

(sleep 100) & exit

Open other terminal

ps aux | grep sleep

Process is still alive.

Image (Asset 13/28) alt=
Sathya
46.4k27137236
answered Aug 7 '12 at 5:18
Image (Asset 14/28) alt=
jitendra
411
   upvote
  flag
This 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" $@)& – Ron E Dec 3 '13 at 21:10

Backgrounding and foregrounding a job is probably one of the very first things every Unix sys-admin should know.

Here is how it is done:

./script.sh
# suspend process
{ctrl-Z}
# background process
bg
# list all backgrounded jobs
jobs
# bring it back to foreground
fg
answered May 22 '13 at 23:00
Image (Asset 15/28) alt=
djangofan
1,35261930

Try daemon -- should be available from your friendly package manager and comprehensively take care of every way of disassociating itself from the terminal.

answered Mar 23 '09 at 12:10
Image (Asset 16/28) alt=
ShiDoiSi
1215

In my .bashrc, I have these functions for precisely that purpose:

function run_disowned() {
    "$@" & disown
}

function dos() {
    # run_disowned and silenced

    run_disowned "$@" 1>/dev/null 2>/dev/null
}

Prefix a command with dos to run it detached from the terminal.

The function is written to work with bash and zsh.

answered Jun 14 '15 at 17:53
Image (Asset 17/28) alt=
mic_e
20914
   upvote
  flag
I 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 use 1> and 2> , because you're using disown, which means you are using bash, and in bash you can just easily do &> to redirect both stdout and stderr – Serg Aug 7 at 18:53
   upvote
  flag
I 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. – mic_e Aug 8 at 7:17

I use the following script to do this. It stops the process printing to the terminal, detaches with nohup, and exits with the return status if the command finishes within the TIMEOUT.

#!/bin/bash

TIMEOUT=0.1

CMD=( "$@" )
#Could have some shortcuts here, e.g. replace "somefile.c" with "gedit somefile.c"

#use nohup to run the command, suppressing its output and allowing the terminal to be closed
#also send nohup's output to /dev/null, supressing nohup.out
#run nohup in the background so this script doesn't block
#print the command for debugging and to see bash variable expansion
printf "%q " "${CMD[@]}"
echo
nohup "${CMD[@]}" >/dev/null 2>&1 &
NOHUP_PID=$!

#kill this script after a short time, exiting with success status - command is still running
#this is needed as there is no timeout argument for `wait` below
MY_PID=$$
trap "exit 0" SIGINT SIGTERM
sleep $TIMEOUT && kill $MY_PID 2>/dev/null & #ignore "No such process" error if this exits normally

#if the command finishes before the above timeout, everything may be just fine or there could have been an error
wait $NOHUP_PID
NOHUP_STATUS=$?
#print an error if there was any. most commonly, there was a typo in the command
[ $NOHUP_STATUS != 0 ] && echo "Error: $CMD"
#return the exit status of nohup, whatever it was
exit $NOHUP_STATUS

Usage example:

>>> run false
false
Error: false
>>> echo $?
1
>>> run true
true
>>> run sleep 10
sleep 10
>>>
answered Sep 21 '14 at 4:42
Image (Asset 18/28) alt=
jozxyqk
556824

I have found on Mac OS X that I need to use both nohup AND disown to ensure that the child process is not torn down with the terminal.

answered Jun 19 '10 at 16:46
Image (Asset 19/28) alt=
aaron
1212

Your Answer

 
community wiki

asked

7 years ago

viewed

187174 times

active

12 months ago

Hot Network Questions

Technology Life / Arts Culture / Recreation Science Other
  1. Stack Overflow
  2. Server Fault
  3. Super User
  4. Web Applications
  5. Ask Ubuntu
  6. Webmasters
  7. Game Development
  8. TeX - LaTeX
  1. Programmers
  2. Unix & Linux
  3. Ask Different (Apple)
  4. WordPress Development
  5. Geographic Information Systems
  6. Electrical Engineering
  7. Android Enthusiasts
  8. Information Security
  1. Database Administrators
  2. Drupal Answers
  3. SharePoint
  4. User Experience
  5. Mathematica
  6. Salesforce
  7. ExpressionEngine® Answers
  8. Cryptography
  1. Code Review
  2. Magento
  3. Signal Processing
  4. Raspberry Pi
  5. Programming Puzzles & Code Golf
  6. more (7)
  1. Photography
  2. Science Fiction & Fantasy
  3. Graphic Design
  4. Movies & TV
  5. Music: Practice & Theory
  6. Seasoned Advice (cooking)
  7. Home Improvement
  8. Personal Finance & Money
  1. Academia
  2. more (8)
  1. English Language & Usage
  2. Skeptics
  3. Mi Yodeya (Judaism)
  4. Travel
  5. Christianity
  6. English Language Learners
  7. Japanese Language
  8. Arqade (gaming)
  1. Bicycles
  2. Role-playing Games
  3. Anime & Manga
  4. more (18)
  1. Mathematics
  2. Cross Validated (stats)
  3. Theoretical Computer Science
  4. Physics
  5. MathOverflow
  6. Chemistry
  7. Biology
  8. Computer Science
  1. Philosophy
  2. more (3)
  1. Stack Apps
  2. Meta Stack Exchange
  3. Area 51
  4. Stack Overflow Careers
site design / logo © 2016 Stack Exchange Inc; user contributions licensed under cc by-sa 3.0 with attribution required
rev 2016.10.10.4050