How can I run a command which will survive terminal close?

Sometimes I want to start a process and forget about it. If I start it from the command line, like this:

redshift

I can’t close the terminal, or it will kill the process. Can I run a command in such a way that I can close the terminal without killing the process?

Asked By: Matthew

||

One of the following 2 should work:

$ nohup redshift &

or

$ redshift &
$ disown

See the following for a bit more information on how this works:

Answered By: Steven D

If your program is already running you can pause it with Ctrl-Z, pull it into the background with bg and then disown it, like this:

$ sleep 1000
^Z
[1]+  Stopped                 sleep 1000
$ bg
$ disown
$ exit
Answered By: Stefan

You can run the process like this in the terminal

setsid process

This will run the program in a new session, as explained in my article here.

Answered By: hanoo

Good answer is already posted by @Steven D, yet I think this might clarify it a bit more.

The reason that the process is killed on termination of the terminal is that the process you start is a child process of the terminal. Once you close the terminal, this will kill these child processes as well. You can see the process tree with pstree, for example when running kate & in Konsole:

init-+
     ├─konsole─┬─bash─┬─kate───2*[{kate}]
     │         │      └─pstree
     │         └─2*[{konsole}]

To make the kate process detached from konsole when you terminate konsole, use nohup with the command, like this:

nohup kate &

After closing konsole, pstree will look like this:

init-+
     |-kate---2*[{kate}]

and kate will survive. 🙂

An alternative is using screen/tmux/byobu, which will keep the shell running, independent of the terminal.

Answered By: gertvdijk

I have a script (I called run) to:

  • Run arbitrary commands in the background
  • Stop them from being killed with the terminal window
  • Suppress their output
  • Handles exit status

I use it mainly for gedit, evince, inkscape etc that all have lots of annoying terminal output. If the command finishes before TIMEOUT, nohup’s exit status is returned instead of zero. Contents of run:

#!/bin/bash

TIMEOUT=0.1

#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
nohup "${@}" >/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 ${@}"
#return the exit status of nohup, whatever it was
exit $NOHUP_STATUS

Examples:

>>> run true && echo success || echo fail
success
>>> run false && echo success || echo fail
Error false
fail
>>> run sleep 1000 && echo success || echo fail
success
>>> run notfound && echo success || echo fail
Error notfound
fail
Answered By: jozxyqk

The shell-only way to do all this is to close stdin and background the command:

command <&- & 

Then it won’t quit when you quit the shell. Redirecting stdout is a nice optional thing to do.

Disadvantage is that you can’t do this after the fact.

Answered By: w00t

Though all of the suggestions work well, I’ve found my alternative is to use screen, a program that sets up a virtual terminal on your screen.

You might consider starting it with screen -S session_name. Screen can be installed on virtually all Linux and Unix derivatives. Hitting Ctrl+A and (lower case) C will start a second session. This would allow you to toggle back and forth between the initial session by hitting Ctrl+A and 0 or the newer session by hitting Ctrl+A and 1. You can have up to ten sessions in one terminal. I used to start a session at work, go home, ssh into my work machine, and then invoke screen -d -R session_name. This will reconnect you to that remote session.

Answered By: apolinsky

You can set a process (PID) to not receive a HUP signal upon logging out and closing the terminal session. Use the following command:

nohup -p PID
Answered By: tony

I prefer:

(applicationName &)

for example:
linux@linux-desktop:~$ (chromium-browser &)

Make sure to use parenthesis when type the command!

Answered By: daGo

Arguably similar to the answer offered by apolinsky, I use a variant on screen. The vanilla command is like this

screen bash -c 'long_running_command_here; echo; read -p "ALL DONE:"'

The session can be disconnected with Ctrl ACtrl D and reconnected in the simple case with screen -r. I have this wrapped in a script called session that lives in my PATH ready for convenient access:

#!/bin/bash
#
if screen -ls | awk '$1 ~ /^[1-9][0-9]*.'"$1"'/' >/dev/null
then
    echo "WARNING: session is already running (reattach with 'screen -r $1')" >&2
else
    exec screen -S "$1" bash -c "$@; echo; echo '--------------------'; read -p 'ALL DONE (Enter to exit):'"
    echo "ERROR: 'screen' is not installed on this system" >&2
fi
exit 1

This only works when you know in advance you want to disconnect a program. It does not provide for an already running program to be disconnected.

Answered By: roaima

Similarly to other answers posted before, one can transfer a running process to use screen retrospectively thanks to reptyr and then close the terminal. The steps are described in this post.
The steps to take are:

  1. Suspend the process
  2. Resume the process in the background with bg
  3. disown the process
  4. Launch a screen session
  5. Find the PID of the process
  6. Use reptyr to take over the process
Answered By: user308879