After running sleep 10 &
interactively and then immediately closing the terminal from which the command is run, the sleep
command terminates before 10 seconds.
But when this command is put to a script:
# this is a file named testfile.sh
sleep 10 &
and later executed as bash testfile.sh
, the sleep
command persists until completion even after the terminal is closed.
Why in one case sleep
stops right after the terminal is closed, while in another it continues executing?
In Bash, &
starts a background job. When you close the terminal
window the terminal emulator sends SIGHUP signal to Bash which in turn
forwards it to all jobs as explained in man bash
:
The shell exits by default upon receipt of a SIGHUP. Before exiting, an interactive shell resends the SIGHUP to all jobs, running or stopped.
The default action of SIGHUP is to terminate the process as explained
in man 7 signal
:
SIGHUP P1990 Term Hangup detected on controlling terminal
But when you run a sleep 10 &
in a script run using bash testfile.sh
you don't run a job and when the parent process - the
script - exits, sleep process loses its parent, is adopted by init (PID 1) and carries on:
$ ps aux | grep '[s]leep 10'
ja 9001 0.0 0.0 3156 1920 pts/8 S 20:32 0:00 sleep 10
$ grep PPid /proc/9001/status
PPid: 1
When Bash receives SIGHUP it doesn't forward it to background jobs
because there aren't any - testfile.sh hasn't been run with &
and sleep isn't even one of its descendant processes anymore.