When to use NOHUP

nohup

I would like to know the purpose of nohup these days.

I ask because I read this

Nohup is short for “No Hangups.” It’s not a command that you run by itself. Nohup is a supplemental command that tells the Linux system not to stop another command once it has started. That means it’ll keep running until it’s done, even if the user that started it logs out. The syntax for nohup is simple and looks something like this:

nohup sh your-script.sh &

Notice the “&” at the end of the command. That moves the command to the background, freeing up the terminal that you’re working in.

Nohup works with just about any command that you run in the terminal. It can be run with custom scripts as well as standard system commands and command line utilities.

With using linux distributions such as SLES 11.4, or RHEL/CentOS 7.x, I can

  • remote log in to linux over the network via SSH
  • run the simple program below, or any other, doing ./a.out &
  • log out of linux; type exit in the putty SSH terminal
  • my sample program below, or any other including bash, csh, or tcsh shell scripts, run to completion just fine without the need for nohup
  • typing exit in putty to close an SSH session, I would think that qualifies as a logout?

Is there any purpose or value with nouhup today? Is it a kernel >= 3.x thing? For however long I can remember (kernel >= 2.6) I've never used nohup and have always just use & with no problems.

Can someone give me a practical scenario where nohup would be used?

#include <stdlib.h>
#include <stdio.h>

/*
    sample C code, to print numbers to a file named zz.tmp
    the numbers 0 to 29 over 30 seconds
*/

int main ( int argc, char *argv[] )
{
   FILE *fp;
   int i;

   i = 0;
   fp = fopen("zz.tmp", "w" );

   while ( i < 30 )
   {
      fprintf( fp, "%d\n", i++ );
      sleep( 1 );
   }
   fclose( fp );
   return 0;
}

mysleep.sh

#!/bin/bash

sleep 1000

On Centos 7.7, optiplex pc login with keyboard & mouse, my account is bash. I do nohup ./mysleep.sh and then control-z. When typing jobs I see [1]+ Stopped nohup ./mysleep.sh

A ps -ef | grep mysleep shows that process id existing, but if I close the terminal window via X in upper right corner, that process goes away so it seems nohup is not working?

Best Answer

remote log in to linux over the network via SSH ... log out of linux; type exit in the putty SSH terminal

Can someone give me a practical scenario where nohup would be used?

Sure. Assuming your shell is bash (see below why), instead of typing exit or ^D, type ~. at the beginning of a line, which will cause your ssh client to disconnect:

$ ssh localhost
ssh$ sleep 3600 &
[1] 5765
ssh$ ~.
ssh$ Connection to localhost closed.
$ ps 5765
  PID TTY      STAT   TIME COMMAND

You can use your program instead of sleep; and instead of disconnecting via ~., you can kill your ssh client or crash the machine it runs on. You want your process to survive this? Use nohup ;-)

Breaking the connection will cause the server process which manages its other end to exit, causing the kernel (any Unix/Linux kernel) to tear down the pseudo-terminal ssh had created, and to send a SIGHUP signal to the session leader (the bash shell), which according to the bash manual:

The shell exits by default upon receipt of a SIGHUP. Before exiting, an interactive shell resends the SIGHUP to all jobs, running or stopped. Stopped jobs are sent SIGCONT to ensure that they receive the SIGHUP.

Many people confuse this bash feature with a) the regular job control thing implemented by the kernel, which will only send a SIGCONT/SIGHUP pair to the stopped, not to the running jobs [1] and b) another bash feature (shopt -s huponexit) which causes a login bash shell to send a SIGHUP to its jobs even when exiting normally (eg. via exit).

[1] a stopped job is a job (= process group) which contains at least one stopped process. A process is stopped as an effect of the default action of a signal like SIGTSTP, SIGSTOP, SIGTTIN or SIGTTOU. Processes which are "sleeping" on a blocking system call like read, nanosleep, select, etc are not considered stopped, but running.

Why nohup may not always help

nohup just sets the disposition of SIGHUP to ignore and does some redirections, it does not guarantee that the process will not be killed by other ways.

a) If the nohup .. job is stopped, an interactive bash will also send it a SIGTERM signal, not just a SIGHUP/SIGCONT pair:

If an attempt to exit bash is made while jobs are stopped [...] the shell prints a warning message [...] If a second attempt to exit is made without an intervening command, the shell does not print another warning, and any stopped jobs are terminated.

[terminated = sent a SIGTERM signal; this is another ksh/bash feature, not present in all shells]

All this can be worked around by simple tricks like double-forks and by creating a new session with setsid(1), but

b) systemd may also "clean up" a logged-out session by forcefully killing (with SIGTERM followed by SIGKILL) any left-over processes if its KillUserProcesses setting is on, which is the default in some distros.

Related Question