Nohup and Disown

When we log out or type exit in a terminal, a hangup signal is sent to the shell, terminating all its child processes.

The term used is hungup, as computer users from the last century used modems to connect their terminals to mainframes. When they hung up the phone, a SIGHUP was sent, and the connection was terminated.

However, often we want to start a program and let it continue running even after we log out or close the terminal emulator window.
Something similar can be done with GNU Screen or Tmux, but opening these programs just for this purpose seems like overkill, besides, some computers do not have Screen installed, and this is not a valid option to use in scripts.

Nohup

For these cases, there is nohup (“no hangup”), which makes the process immune to SIGHUP.

In my bash, just precede the command with nohup and send it to the background (&), and we can close the terminal without any issues:

julio@julio-acer ~ $ nohup dropboxd &

But the same does not work in ZSH:

julio@julio-acer ~> nohup dropboxd &
  [1] 13434
  nohup: ignoring input and appending output to ‘nohup.out’
julio@julio-acer ~> exit
  zsh: you have running jobs.

Trying to exit again will abruptly terminate the program.

This happens because there are still connections to stdin, stdout, and stderr. If we redirect them to /dev/null (or another file), we can exit the shell (exit or logout) without any issues:

julio@julio-acer ~> nohup dropboxd &> /dev/null < /dev/null &!
julio@julio-acer ~> exit

Disown

But what if you started a program without nohup and want to log out without having to terminate it?

In Bash and ZSH, there is the disown command, which disassociates a job from the current shell (removing it from the job list). This allows you to close the shell without interrupting the job.

julio@julio-acer ~> dropboxd
^Z
[1]  + 23042 suspended  dropboxd
julio@julio-acer ~> bg %1
[1]  + 23042 continued  dropboxd
julio@julio-acer ~> jobs
[1]  + running    dropboxd
julio@julio-acer ~> disown %dropboxd
julio@julio-acer ~> jobs
julio@julio-acer ~> ps 23042
  PID   TTY      STAT   TIME  COMMAND
  23042 pts/7    SNl    0:02  /opt/dropbox/dropbox

julio@julio-acer ~> exit

From man bash, we have:

disown [-ar] [-h] [jobspec …]
Without options, each jobspec is removed from the table of active jobs. If jobspec is not present, and neither -a nor -r is supplied, the shell’s notion of the current job is used. If the -h option is given, each jobspec is not removed from the table, but is marked so that SIGHUP is not sent to the job if the shell receives a SIGHUP. If no jobspec is present, and neither the -a nor the -r option is supplied, the current job is used. If no jobspec is supplied, the -a option means to remove or mark all jobs; the -r option without a jobspec argument restricts operation to running jobs. The return value is 0 unless a jobspec does not specify a valid job.

An interesting option is -h, which makes disown behave exactly like nohup. However, this option is exclusive to Bash’s disown and does not work in ZSH.

We can also call disown along with the program. The functionality is almost the same as nohup, and since I don’t need to worry about redirecting streams (stdin, stdout, stderr), I almost always use disown instead of nohup:

julio@julio-acer ~> dropboxd& disown && exit
Julio Batista Silva
Julio Batista Silva
Data Engineer

I’m a computer engineer passionate about science, technology, photography, and languages. Currently working as a Data Engineer in Germany.

comments powered by Disqus