Job control in Bash

Job Control

When you are in an interactive session, and a command is launched, bash will wait for the termination of the command. The “exit” status (return code) is kept in "$?" shell variable.

Be aware that "$?" collects the return code for the last executed command. This is important when pipelining commands. Also, if you run echo $? for a second time, it will have the status of the previous echo.

Whens launching “directly” a command, it is said that is running in the foreground. Adding an & at the end of the command will send th command to be run in the background and the bash prompt will get back immediately.

You can stop send to the background a running command with the ctrl + z keyboard combination.

The jobs internal bash function will list all jobs being run. It will produce an output similar to [1]+ Stopped sleep 60, where [1] is the internal job number.

With fg %n you can bring to the foreground and resume execution any job, being n the job number. Following the previous example: fg %1. It w

With bg %n you can bring to the background and resume execution any job, being n the job number. Following the previous example: bg %1.

The next console capture shows this in action, with the sleep 60 command (this is /bin/sleep binary, as sleep is not an built-in bash command)

mycomputer ~ $ jobs
mycomputer ~ $ fg
bash: fg: current: no such job
mycomputer ~ $ sleep 60
^Z                                            <-- ctrl-z  (stop and go background)
[1]+  Stopped                 sleep 60
mycomputer ~ $ date
Sun May 10 12:37:06 CEST 2020
mycomputer ~ $ jobs
[1]+  Stopped                 sleep 60
mycomputer ~ $ fg %1
sleep 60
^Z                                            <-- ctrl-z  (stop and go background)
[1]+  Stopped                 sleep 60
mycomputer ~ $ date
Sun May 10 12:38:17 CEST 2020
mycomputer ~ $ jobs
[1]+  Stopped                 sleep 60
mycomputer ~ $ bg %1
[1]+ sleep 60 &
mycomputer ~ $ jobs
[1]+  Done                    sleep 60
mycomputer ~ $ date
Sun May 10 12:38:57 CEST 2020
mycomputer ~ $  

Get much more information about job control (wait, kill, at:

7.1 Job Control Basics in the Bash Manual or at 15.1. Job Control Commands in the Advanced Bash-Scripting Guide.

nohup command

Although more related to terminal control and NOT to job control, long running jobs running in the background with benefit with the usage of /usr/bin/nohup, like in nohup verylongtask.sh &.

Without nohup, if you launch the job and decide to logout from the terminal, the job will be automatically killed as it does not have anymore a terminal associated with it (by default, all processes launched in a terminal have this information set in their task_struct, more precisely in the struct tty_struct, which in turn is defined in the Include/linux/tty.h kernel file)

As you can see in the nohup man page capture below, it will run the program without a TTY (terminal) associated and therefore ignoring the SIGHUP signal sent automatically to all processes running in your bash session when you logout.

More about SIBHUB at Wikipedia

NOHUP(1)                     User Commands                          NOHUP(1)

NAME
       nohup - run a command immune to hangups, with output to a non-tty

SYNOPSIS
       nohup COMMAND [ARG]...
       nohup OPTION

DESCRIPTION
       Run COMMAND, ignoring hangup signals.

Also, the Bash manual states that

The shell exits by default upon receipt of a SIGHUP. Before exiting, an interactive shell resends the SIGHUP to all jobs, running or stopped. Stopped jobs are sent SIGCONT to ensure that they receive the SIGHUP. To prevent the shell from sending the SIGHUP signal to a particular job, it should be removed from the jobs table with the disown builtin (see Job Control Builtins) or marked to not receive SIGHUP using disown -h.

If the huponexit shell option has been set with shopt (see The Shopt Builtin), Bash sends a SIGHUP to all jobs when an interactive login shell exits.


https://serverfault.com/questions/117152/do-background-processes-get-a-sighup-when-logging-off