bashshellbackground-process

Difference between interactive process background and from script


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?


Solution

  • 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.