Understanding Foreground and Background Processes in Linux (fg, bg, Ctrl+C, Ctrl+Z)
When working in the Linux terminal, it is important to understand how foreground processes, background processes, and job control work. Linux provides powerful keyboard signals and commands such as Ctrl+C, Ctrl+Z, bg, and fg to manage running programs.
In this article, we will explore these concepts using a simple Bash script and observe how Linux handles signals and process states.
Example Script
Below is a simple script that runs indefinitely and traps the SIGINT signal (Ctrl+C).
[root@oel01db Shell-Scripting]# cat o1-trap-with-sigint-with-no-exit.sh
#!/usr/bin/env bash
my-func() {
echo "hello world"
}
trap my-func SIGINT
while true; do
sleep 1
echo running
done
[root@oel01db Shell-Scripting]#
Running the Script
[root@oel01db Shell-Scripting]# bash o1-trap-with-sigint-with-no-exit.sh
running
running
running
running
^Chello world
running
running
^Chello world
running
running
^Z
[1]+ Stopped bash o1-trap-with-sigint-with-no-exit.sh
[root@oel01db Shell-Scripting]#
Understanding Ctrl+C and SIGINT
Normally, pressing Ctrl+C sends a signal called SIGINT (Signal Interrupt) to the running process.
The default behavior of SIGINT is to terminate the process immediately.
However, in our script we used:
trap my-func SIGINT
This means:
When SIGINT is received, do not terminate the program. Instead, run the function
my-func.
So when Ctrl+C is pressed, the script prints:
hello world
and then continues running.
Because the function does not contain an exit command, the script keeps running indefinitely.
In other words, we have hijacked the default behavior of Ctrl+C.
Understanding Ctrl+Z and SIGTSTP
Unlike Ctrl+C, pressing Ctrl+Z sends a different signal called:
SIGTSTP (Terminal Stop)
This signal pauses the process instead of terminating it.
In our example:
^Z
[1]+ Stopped bash o1-trap-with-sigint-with-no-exit.sh
This means:
-
The process is not terminated
-
It is paused
-
It remains loaded in memory (RAM)
-
It consumes no CPU while stopped
The process is now waiting for instructions from the shell.
Viewing Jobs
Linux keeps track of suspended and background tasks as jobs.
You can list them using:
jobs
Each job is assigned a Job ID, displayed inside brackets like [1].
Moving a Stopped Job to the Background
If you type bg, the stopped job resumes execution but runs in the background.
[root@oel01db Shell-Scripting]# bg
[1]+ bash o1-trap-with-sigint-with-no-exit.sh &
[root@oel01db Shell-Scripting]# running
running
running
^C
[root@oel01db Shell-Scripting]# running
running
running
Important observation:
Even though the script runs in the background, its stdout is still connected to the terminal, so you continue to see the output.
Why Ctrl+C Does Not Work in the Background
When you pressed:
^C
nothing happened.
This is because keyboard signals like Ctrl+C are only sent to the foreground process group.
Since the script is running in the background, it does not receive the signal.
Bringing the Job Back to the Foreground
To interact with the job again, you must bring it to the foreground using the fg command.
[root@oel01db Shell-Scripting]# running
running
fg
bash o1-trap-with-sigint-with-no-exit.sh
running
running
^Z
[1]+ Stopped bash o1-trap-with-sigint-with-no-exit.sh
[root@oel01db Shell-Scripting]#
Step-by-step sequence
-
Type
fgand press Enter.
Note: You might have to type it while the word running is being printed repeatedly. Just type it and press Enter; Bash will still read it.
-
The script returns to the foreground.
-
The message appears again:
bash o1-trap-with-sigint-with-no-exit.sh
-
The
runningmessages continue. -
Now press Ctrl+Z again.
-
The terminal immediately reports:
[1]+ Stopped
The script is now paused again.
Killing the Job
If you want to terminate the stopped job, first check the job list:
[root@oel01db Shell-Scripting]# jobs
[1]+ Stopped bash o1-trap-with-sigint-with-no-exit.sh
[root@oel01db Shell-Scripting]#
Then terminate it using the job ID:
[root@oel01db Shell-Scripting]# kill %1
[1]+ Stopped bash o1-trap-with-sigint-with-no-exit.sh
[root@oel01db Shell-Scripting]#
[1]+ Terminated bash o1-trap-with-sigint-with-no-exit.sh
[root@oel01db Shell-Scripting]#
The %1 refers to the job number [1].
We can also use kill %% to terminate the most recent job in the jobs list).
Important Job Control Commands
| Command | Purpose |
|---|---|
Ctrl+C | Sends SIGINT (terminate by default) |
Ctrl+Z | Sends SIGTSTP (pause process) |
jobs | Lists background and stopped jobs |
bg | Resume a stopped job in background |
fg | Bring a job to the foreground |
kill %jobid | Terminate a job |
Useful Insight: Job IDs vs Process IDs
A job ID is managed by the shell.
Example:
[1]
But every job also has a real process ID (PID).
You can see it with:
ps
or
jobs -l
Example:
jobs -l
[1]+ 12345 Stopped bash o1-trap-with-sigint-with-no-exit.sh
Here:
-
1 → Job ID
-
12345 → Process ID
Real-World Importance
Understanding foreground and background processes is essential for:
-
running long scripts
-
managing database jobs
-
monitoring services
-
controlling log streams
-
writing robust shell scripts
-
handling signals safely
Linux job control allows you to pause, resume, move, and terminate processes without killing your terminal session, which is extremely powerful for system administrators and developers.
No comments:
Post a Comment