Read

Module 6 · Processes and jobs

nohup and keeping work alive

Why closing a terminal kills your jobs, how nohup and setsid protect a long task from the hangup, where its output goes, and how to prove from /proc that a process will survive.

What you will learn

  • Explain SIGHUP and why background jobs die with their terminal.
  • Run a long job with `nohup … > log 2>&1 &` and know when `nohup.out` appears.
  • Detach a process completely with `setsid`, and check SigIgn in `/proc/PID/status`.

The hangup

You start a three-hour job over SSH with &, close the laptop, and the next morning the job is dead. The culprit is SIGHUP, signal 1, named after the modem *hang-up* of the days when terminals were connected by phone line. When a terminal goes away, the kernel sends HUP to the session's leader, your shell, and the shell passes it on to its jobs. HUP's default action is to terminate, so every job started from that terminal dies with it, background or not. The & only freed your keyboard; it never detached the job from the terminal.

nohup: ignore the hangup

nohup CMD sets HUP to *ignored* and then runs CMD in its own place. Ignored signals stay ignored across exec, so CMD and everything it starts shrug the hangup off. nohup also worries about output: if standard output is a terminal, which will soon disappear, it sends the output to a file called nohup.out in the current directory (or $HOME/nohup.out if that is not writable), and standard error follows it. nohup does not put the command in the background; you still add &. The professional form names its own log so nothing lands in a surprise nohup.out:

~% nohup sh -c 'echo started; sleep 600' &
~% cat nohup.out
started
~% nohup sleep 1500 > /root/lab/job.log 2>&1 &
[1] 946
~% grep SigIgn /proc/946/status
SigIgn:	0000000000000001

Proving it with /proc and killall -HUP

Every process's /proc/PID/status has a SigIgn line: a hexadecimal bit mask of the signals it ignores, where bit 1 (value 1) is HUP, value 2 is INT and value 4 is QUIT. If the last hex digit is odd, HUP is ignored and the process will survive a hangup. Depending on how it was started you may see …0006 for a plain background job (the shell made it ignore INT and QUIT) and …0007 for the same job under nohup. Or simply test it: start one plain and one nohup'd sleep, then killall -HUP sleep. Only the protected one is still in ps afterwards.

setsid: leave the terminal behind

~% setsid sleep 1502 &
~% ps -o pid,pgid,sid,tty,args | grep '[s]leep 1502'
  954   954   954 ?      sleep 1502

setsid CMD goes further: it runs CMD in a brand-new session with no controlling terminal, so there is no terminal whose hangup could reach it, and Ctrl-C in your terminal never touches it either. ps shows its session ID equal to its own PID and its TTY as ?. Inside a script, trap '' HUP makes the script itself ignore the hangup, just like nohup. bash users may know disown; ash does not have it. For anything that must run for days, the right home is a service managed by init, or a terminal multiplexer such as tmux or screen on a full system.

FormSurvives hangup?Output
cmd &NoTo the terminal
nohup cmd &Yesnohup.out if stdout was a terminal
nohup cmd > log 2>&1 &YesYour log file
setsid cmdYes, no terminal at allWherever you redirect it

Commands in this lesson

CommandWhat it does
nohup CMD &Run CMD immune to hangups, in the background.
nohup CMD > log 2>&1 &Same, with output in a log you chose.
setsid CMDRun CMD in a new session without a controlling terminal.
grep SigIgn /proc/PID/statusIgnored signals; an odd last digit means HUP is ignored.
killall -HUP NAMESimulate a hangup for every process named NAME.
trap '' HUPMake the current shell or script ignore HUP.

Quiz

  1. Which signal kills your jobs when the terminal disappears?

    • TERM
    • HUP
    • INT
  2. You type `nohup ./backup.sh` without `&`. What happens?

    • It runs in the background anyway
    • It runs in the foreground; the prompt returns only when it ends
    • nohup refuses to run
  3. Where does the output of `nohup CMD &` go when standard output is a terminal?

    • /dev/null
    • To nohup.out in the current directory
    • To /var/log/nohup
  4. A plain `sleep` and a nohup'd `sleep` are running. After `killall -HUP sleep`, what is left?

    • Nothing
    • Only the nohup'd one
    • Both
  5. What does `setsid CMD` give the command?

    • Root privileges
    • A new session with no controlling terminal
    • A lower nice value

Practice

  1. Start `sleep 1900` in the background, immune to hangups, with its output and errors going to `/root/lab/l59/out.log`.

  2. Start `sleep 1901` in a brand-new session with no controlling terminal.

  3. Two sleeps are running: `sleep 1902` was started with nohup, `sleep 1903` was not. Simulate a hangup by sending HUP to every `sleep` by name, and watch which one survives.

Open this lesson in the app to do the tasks in a real Linux machine and have them checked.