Managing Foreground & Background Processes
11 min read·Jan 1, 2025
By default, when executing a command, the resulting process created and executed by the shell runs in the foreground of the terminal, thus blocking its usage until it completes.
While most processes are short-lived and complete their execution in a matter of milliseconds or a few seconds, this behaviour is not desirable for longer-lived processes, such as web servers or processing scripts.
Running a process in the background
To run a process in the background, you can append an ampersand character & to your command as follows:
$ command &
This will cause the shell to execute the resulting process of that command as a background task called a job and immediately give you the command prompt back to perform other tasks.
Additionally, the shell will output the job number and process identifier of the task in the following format:
[job_number] process_identifier
Where:
- The job number is an integer assigned by the job manager to identify a running or suspended background process.
- The process identifier is an integer assigned by the system itself to uniquely identify an active process.
Note: Whenever running a process in the background that takes a while to complete, such as a script, the shell will automatically prompt you with a message upon termination, so you don't have to keep track of it.
Redirecting the standard streams
Although jobs are executed in the background, their standard streams are, by default, still attached to the terminal they are launched from.
To prevent a job from disrupting the usage of the terminal by writing undesirable logs and errors to it, you can use the output redirection operators to redirect or silence the standard output and standard error streams:
$ command fd> file &
Example
This command will run the ping command in the background and write its output into the google.com.log file instead of the terminal's standard output:
$ ping -c 3 google.com > google.com.log 2>&1 &
[1] 46637
$ cat google.com.log
PING google.com (216.58.213.78): 56 data bytes
64 bytes from 216.58.213.78: icmp_seq=0 ttl=116 time=7.610 ms
64 bytes from 216.58.213.78: icmp_seq=1 ttl=116 time=8.257 ms
64 bytes from 216.58.213.78: icmp_seq=2 ttl=116 time=7.404 ms
--- google.com ping statistics ---
3 packets transmitted, 3 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 7.404/7.757/8.257/0.363 ms
Note: The
pingcommand is used to send echo requests to a server to test its connectivity and response round-trip time.
Listing background jobs
To list the jobs currently running in the shell's background, you can use the jobs command:
$ jobs
Which will produce a similar output
[job]+ status command
Where:
jobis the job number.statusis the current status of the job (i.e.,Running,Stopped,Done).commandis the command the job was launched from.
Example
This command will show 1 running job and 1 terminated job:
$ jobs
[1]- Running npm run start &
[2]+ Done ./script.sh &
Bringing a process to the foreground
To bring a job back to the foreground of the shell, you can use the fg command as follows:
$ fg %job
Where job is the job number obtained using the jobs command.
Note: When executed without arguments, the
fgcommand will automatically bring the most recent job indicated by a plus sign (+) to the foreground.
Sending a foreground process to the background
To send a process that currently runs in the foreground of the shell to the background, you must first suspend (i.e., pause) its execution using the CTRL + Z key combination:
$ command
^Z
[1]+ Stopped command
Then restart the suspended process in the background using the bg command:
$ bg %job
Where job is the job number returned by CTRL + Z.
Killing a running process with signals
In Unix-like operating systems, one way to stop a process is to send a signal to it, which is a standardized message designed to trigger a specific behaviour, such as a graceful or forceful shutdown.
Some of these signals can be caught or ignored, which means that a process can decide to either intercept them and perform an action in response or just completely ignore them.
Other signals can't be caught or ignored, which means that a process will be forced into a specific behaviour by the operating system.
Killing a foreground process
To kill a foreground process, you can use the CTRL + C key combination as follows:
$ command
^C
Which will send a catchable interrupt signal (i.e. SIGINT) to the process.
Example
This signal will cause the cat command running in the foreground to immediately terminate:
$ cat
Hello, World!
Hello, World!
▮
^C
$
Killing a background process
Rather than bringing a background process to the foreground and killing it using the CTRL + C key combination, you can directly send a terminate signal (i.e. SIGTERM) to the process using the kill command as follows:
$ kill pid ...
Where pid is the job number or process identifier of the running process.
Alternatively, you can send a specific signal using the -s flag as follows:
$ kill -s signal pid ...
Where:
signalis a symbolic signal name (e.g.,INT,KILL).pidis the job number or process identifier of the running process.
Note: that you can find the complete list of signals and their description using the
man signalcommand.
Example
This command will terminate the job number 1:
$ jobs
[1]+ Running command &
$ kill %1
$ jobs
[1]+ Terminated: 15 command
Killing an unresponsive process
It sometimes happens that a process becomes unresponsive and either freezes or refuses to stop.
To forcefully terminate it, you can first get the PID of the desired process using the ps command:
$ ps
Then use the kill command to send a SIGKILL signal to it using its process identifier:
$ kill -s KILL pid
Example
This command will terminate the second shell whose PID is 63427:
$ ps
PID TTY TIME CMD
1759 ttys001 0:00.03 -bash
63427 ttys002 0:00.15 -bash
$ kill -s KILL 63427
Summary
Here's a summary of what you've learned in this lesson:
- The ampersand character
&is used to execute a process in the background of the shell. - The
jobscommand is used to list the processes currently running in the background. - The
fgcommand is used to bring a running job back to the foreground of the shell. - The
CTRL + Zkey combination is used to suspend the execution of a foreground process. - The
bgcommand is used to restart a suspended job in the background. - The
CTRL + Ckey combination is used to kill a process by sending aSIGINTsignal to it. - The
killcommand is used to kill a process by sending an arbitrary signal to it. - The
pscommand is used to list all the processes currently running on the machine.
Enjoying the courses?
I've made these courses completely free so anyone can learn from them. If they've helped you and you'd like to actively support the work behind BackendBrewery, you can leave a tip:
Support BackendBrewery