How to Use Nohup to Run Linux Scripts Unattended

Run Nohup in Linux
(Image credit: Tom's Hardware)

If you are building a robot, sensor platform, weather station then you don’t want the code to stop running when you disconnect from the terminal, and nohup is just the thing for you.In this how-to, we will learn how to use nohup via a series of examples

There are times when you want to run a command, and leave it running even after you close a terminal window / SSH session. The simplest way is using nohup (no hangups) which will run any command or executable script long after we close the terminal.

Basic Nohup Use in Linux

At its most basic, nohup can be used with only a single argument, the name of the script / command that we want to run. For example if we had a Bash script called test.sh we could run it as so.

nohup ./test.sh

If the script / command produces standard output, then that output is written to nohup.out and not the terminal. To check the output we can use tail to follow the updates made to the file.

tail -f nohup.out

An Example of Nohup Use

(Image credit: Tom's Hardware)

We created a simple Bash script that every second prints a message to the screen, and updates the value stored in the variable n. Here is the code for that file, called test.sh.

#!/bin/bash
n=0
while true
do
  echo "I keep counting"
  echo $n
  n=$((n+1))
  sleep 1
done

1. Open a text editor and paste the example code.

2. Save the file to your home directory as test.sh.

3. Open a terminal and set test.sh to be executable.

chmod +x test.sh

4. Test that test.sh is executable by running the command. If successful press CTRL + C to stop.

5. Use nohup and use the test.sh as an argument. Note that we need to use ./test.sh to tell the system where to find the script. The only output in the Terminal is “ nohup: ignoring input and appending output to 'nohup.out' “

nohup ./test.sh

6. Open another terminal and use the tail command to follow the updates made to the nohup.out file. You should see “I keep counting” and a number counting upwards scroll across the screen.

tail -f nohup.out

7. Close the terminal running nohup. If asked to confirm closure, select Yes. The terminal running tail -f will keep running, showing that nohup is still running the script. We confirmed this by running htop and searching for test.sh.

(Image credit: Tom's Hardware)

Redirecting the Nohup Output

(Image credit: Tom's Hardware)

Nohup has a limitation. By default it writes to nohup.out, so if we had two instances of nohup being used, they would both write to the same file.

(Image credit: Tom's Hardware)

To get around this we can use redirection to send the output to another file. So let's use nohup along with the ping command to ping one of Google’s DNS servers, and save the output to GooglePing.txt.

1. Open a terminal window.

2. Using the nohup command, use ping 8.8.8.8 as an argument. This will ping one of Google’s DNS servers every second, a useful connectivity test. 

nohup ping 8.8.8.8 > GooglePing.txt

3. Open another terminal and use tail to follow the output of GooglePing.txt. Press CTRL+C when you are ready to stop the tailing the output.

nohup ping 8.8.8.8 > GooglePing.txt

4. In the nohup terminal, press CTRL+C to stop the ping command.

Running a Nohup command in the background

When nohup runs it grabs control of the terminal, effectively disabling it. But with a little more Linux magic we can put the command into the background. By placing the command into the background we can carry on using the terminal.

We’ll reuse the ping example to illustrate.

1. Open a terminal window.

2. Using the nohup command, use ping 8.8.8.8 as an argument then add & to send the command to the background. Note that the output of running this command will be a process ID (PID). We will need this later.

nohup ping 8.8.8.8 > GooglePing.txt &

(Image credit: Tom's Hardware)

3. Open another terminal and use tail to follow the output of GooglePing.txt. 

4. In the nohup terminal press Enter to return to the prompt. The nohup command returns control to us, but the prompt is not present. By pressing Enter we can see the correct terminal prompt.

5. Use the kill command along with the process ID to terminate the background process. If the process is no longer required it is best practice to kill it in order to preserve resources. If we left this example to run it would continually ping Google’s DNS server until the computer was switched off.

kill 28365

(Image credit: Tom's Hardware)
Les Pounder

Les Pounder is an associate editor at Tom's Hardware. He is a creative technologist and for seven years has created projects to educate and inspire minds both young and old. He has worked with the Raspberry Pi Foundation to write and deliver their teacher training program "Picademy".

  • Zé Mau
    I prefer tmux, or the old screen command.
    Reply
  • w_barath
    Admin said:
    How to Use Nohup to Run Linux Scripts Unattended : Read more

    $ autossh user@host -- screen -x -R -t "Title" -h 10000;
    This will let your remote scripts survive disconnects, and when the reconnect occurs you'll have your display back exactly how it left off. Super handy for WiFi and/or mobile connections.

    It's also great if you have a number of remote hosts to admin and you have something like a google free tier compute node that you can shell into and then open multiple screen "windows" to all those remotes. Then you only have to connect to the one screen session to have stable network access to all those other hosts via CRTL-A 0..9 with nice little labels at the bottom of the screen to remind you which is which.


    user@localhost:~$ ssh user@remote.host -- cat \~/.screenrc
    # .screenrc
    defscrollback 10000
    startup_message off

    # mouse scrollback:
    termcapinfo xterm* ti@:te@

    # window list:
    hardstatus on
    hardstatus alwayslastline
    hardstatus string "%{.bW}%-w%{.rW}%n %t%{-}%+w %=%{..G}"

    # mouse can switch windows
    mousetrack on

    # prevent xoff
    bind s split
    P.S. view response in the forum for a screenshot.

    P.P.S. @Les: echo $(( n++ ));
    Reply