Nohup Command Tutorial in Linux with Example Usage

Sarath Pillai's picture
Nohup Command in Linux

Any command that you execute in Linux will have a corresponding process associated with it. Even commands that are generally short lived (like grep, cat, ls, and so on..), will have a process associated with it. All these processes has three things in common.  I must actually say 4 things in common. The fourth thing is the parent process. The only process that does not have a parent is INIT process in Linux.  These four things are mentioned below.

  • Standard Input

  • Standard Output

  • Standard Error

  • Parent Process

The first three mentioned above are indicated using numbers(0, 1 and 2). 0 is used for input, 1 for output and finally 2 for error. By default when you start a process using shell, stdin is attached to whatever you type, and 1 & 2 is the same terminal where you can see the output(as well as the error.)

There is a popular saying in Unix operating systems that “Everything is a file”, even your hardware devices, and network connections and any other external devices are all nothing but some sort of special files to the operating system.

Consider the below before we proceed further.

 

0 is a number for the file that is identified as keyboard in your system.

1 and 2 are numbers for the file that is identified as your computer screen.

 

The correct term to call these 0, 1 and 2 above is file descriptors. So basically these file descriptors indicate input, output and error. In fact if you navigate to /proc in the system, you should be able to see a lot directories there, under the name of the process id.

 

For example, login to the same machine using two different terminals. In one terminal, find out the process id number of the bash shell used in the other terminal (you can simply do a ps aux |grep bash). Let’s imagine the bash process id number is 1952. In that case get inside /prod/1952/fd/ and do the below.

 

Related: What is /proc file system in Linux?

 

root@instance-1:~# cd /proc/1952/fd/
root@instance-1:/proc/1952/fd# ls
0  1  2  255
root@instance-1:/proc/1952/fd# echo testing > 1
root@instance-1:/proc/1952/fd#

 

Please note the fact that in the above example 1952 is the pid of the bash shell on the other terminal. Once you execute the above echo command, the content should be visible on the other terminal. Because its actually sending the content to the file descriptor "1", which is the stdout screen. Hence you see the content there on the terminal.

One another interesting thing to note is that 0, 1 and 2 are actually symbolic link to another file called tty file. Basically the terminal file.

In linux, execute the command tty, and it should tell you the terminal name. In my case the name of the other side terminal is /dev/pts/2, hence the below.

 

root@instance-1:/proc/1952/fd# ls -l
total 0
lrwx------ 1 sarath sarath 64 Nov  9 05:01 0 -> /dev/pts/2
lrwx------ 1 sarath sarath 64 Nov  9 05:01 1 -> /dev/pts/2
lrwx------ 1 sarath sarath 64 Nov  9 05:01 2 -> /dev/pts/2
lrwx------ 1 sarath sarath 64 Nov  9 05:01 255 -> /dev/pts/2

 

If you run a process using the shell, the process will also have the same 0, 1 and 2. Basically output, error and input will be in most cases same as that of the shell itself. Hence you see the process output on the terminal itself.  If you logout/exit from the shell, the shell generally gets a signal called SIGHUP.

In most cases, the default setting of bash shell is to send the SIGHUP signal to all the jobs that it started(basically the parent bash process will send SIGHUP to all its children). Which means, as soon as the shell exits, the jobs started using the shell also will exit in most cases.

 

The only case where it does not send SIGHUP to the jobs is if huponexit setting is turned on. You can do that using shopt -s huponexit command in bash shell.

 

You can use another bash shell builtin feature called disown , to prevent jobs from getting SIGHUP. You basically start a process and put it in background. To start a process and put it in background, you basically execute the command followed by "&". (example: my-command &).

 

Related: Disown command in bash shell

 

In this case also, the background job will still use the shell's stdout and stderr (1 & 2). No change when it comes to output of the background process(unless you use some sort of redirection methods like ">", ie: my-command > output.file). Once your job is in background, you can execute disown -h %1. Please note the fact that %1 stands for job number (which you can find out using jobs command).

 

Using the above method you can prevent the job from recieving a SIGHUP when the shell exits. However, the job is still associated to the terminal. Basically there is no way to grab the stdout and stderr of that process once you are logged out from the shell(yes the process wont get SIGHUP, and it will continue to run).

 

So why am I talking about all these, especially if the topic is about "Nohup command". Nohup, as the name indicates prevents a job from recieving the SIGHUP signal. Or in other words, the job started using nohup will ignore SIGHUP signals sent by bash. Apart from this, there are several additional things that are unique to nohup, compared to disown or shopt settings.

 

#nohup somecommand

 

Above shown is the method to execute nohup. Basically prepend your command with nohup. But the above shown method of executing nohup is actually quite useless.

This is because nohup will end the stdin for the process. Which means you cannot pass inputs to a process that is started using nohup as shown above. So its basically useless to your process using nohup and keep the process in foreground (as it cannot accept input). Hence what people generally do is to always put the process in background when started using nohup.

 

#nohup somecommand &

 

Another thing to note about nohup is the fact that it will create a file called nohup.out in the current directory, and send all stdout and stderr to there(ie: 1 and 2 will be pointing to nohup.out file). Lets see this practically. 

root@instance-1:~# nohup sh script.sh &
[1] 3416
root@instance-1:~# nohup: ignoring input and appending output to ‘nohup.out’

 

The output clearly says that its going to ignore input. So forget about input when a command is ran using nohup. But all stdout and stderr will be going to a file called nohup.out in the current directory.

So basically the symlinks that we earlier saw, which linked to the terminal id named /dev/dev/pts2 should now be linked to nohup.out file. See below.

 

root@instance-1:~# ls -l /proc/3416/fd/
total 0
l-wx------ 1 root root 64 Nov  9 06:55 0 -> /dev/null
l-wx------ 1 root root 64 Nov  9 06:55 1 -> /root/nohup.out
lr-x------ 1 root root 64 Nov  9 06:55 10 -> /root/script.sh
l-wx------ 1 root root 64 Nov  9 06:55 2 -> /root/nohup.out

Note that 1 and 2 are pointing to nohup.out file.

 

Another important thing to note about nohup is the fact that it does nothing to the shell's job control. Basically the jobs started with nohup will still be present inside the shell's job list. But it wont get killed when the shell exits.

 

You can send the stderr and stdout to two different files using the below method. In this, it will not generate the nohup.out file at all.

 

root@instance-1:~# nohup ./script.sh > my-output 2> my-error &
[1] 4034
root@instance-1:/proc/4034/fd# ls -l
total 0
l-wx------ 1 root root 64 Nov  9 07:16 0 -> /dev/null
l-wx------ 1 root root 64 Nov  9 07:16 1 -> /root/my-output
l-wx------ 1 root root 64 Nov  9 07:16 2 -> /root/my-error
lr-x------ 1 root root 64 Nov  9 07:16 255 -> /root/script.s

 

You can also send both stdout and stderr to the same file of your interest other than nohup.out using the below method.

 

root@instance-1:~# nohup ./script.sh > my-output 2>&1 &
[1] 4178
root@instance-1:~#
root@instance-1:~#
root@instance-1:~# cd /proc/4178/fd
root@instance-1:/proc/4178/fd# ls -l
total 0
l-wx------ 1 root root 64 Nov  9 07:19 0 -> /dev/null
l-wx------ 1 root root 64 Nov  9 07:19 1 -> /root/my-output
l-wx------ 1 root root 64 Nov  9 07:19 2 -> /root/my-output
lr-x------ 1 root root 64 Nov  9 07:19 255 -> /root/script.sh

 

In the above command, 2>&1 indicates that both stdout and stderr should go to that file.

 

Some points to note about nohup is below:

 

  • Nohup does not remove job from shells job table
  • Processes ran using nohup will ignore SIGHUP signals
  • by default nohup.out file is used for everything (stdout and stderr)
  • stdin is not available once a job is executed using nohup (which is why 0 is linked to /dev/null)
Rate this article: 
Average: 4.2 (161 votes)

Add new comment

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
CAPTCHA
This question is for testing whether or not you are a human visitor and to prevent automated spam submissions.