Bash’s process management is surprisingly powerful, letting you orchestrate background tasks like a seasoned conductor, often without realizing it.
Let’s see it in action. Imagine you have a long-running script, heavy_computation.sh, that you don’t want to block your terminal.
# heavy_computation.sh
#!/bin/bash
echo "Starting heavy computation..."
sleep 10
echo "Computation finished."
You can run this script in the background by simply appending an ampersand (&) to the command:
./heavy_computation.sh &
You’ll immediately get a job number and a process ID (PID):
[1] 12345
Starting heavy computation...
This [1] is the job number, and 12345 is the PID. Your terminal is now free. You can run other commands:
echo "I can still type commands!"
sleep 5
To see what’s running in the background, use the jobs command:
jobs
This will show you the status of your background jobs:
[1]+ Running ./heavy_computation.sh &
The + indicates the "current" job, the one that fg or bg would operate on by default. The Running status tells you it’s active.
Now, let’s say you want to bring that background job back to the foreground. Maybe you need to see its output or interact with it. Use fg:
fg %1
The %1 refers to job number 1. Your terminal will now show the rest of the output from heavy_computation.sh and wait for it to finish:
Computation finished.
exit 0
If you wanted to send a job to the background after it’s already running in the foreground, you can press Ctrl+Z. This suspends the process and returns you to the shell. Then, you can use bg %<job_number> to resume it in the background.
# In your terminal:
./another_script.sh
# Press Ctrl+Z
[1]+ Stopped ./another_script.sh
bg %1
[1]+ ./another_script.sh &
The real power comes with controlling these processes. You can send signals to them. The most common signals are SIGTERM (terminate gracefully) and SIGKILL (force terminate). You use the kill command with the PID.
To find the PID of a background job, you can use jobs -p:
jobs -p
This might output:
12345
So, to terminate job 1 (PID 12345) gracefully:
kill 12345
If it doesn’t stop, you can force it:
kill -9 12345
The -9 is the signal number for SIGKILL.
You can also manage processes by name using pkill or killall. pkill sends a signal to processes whose names match a pattern, while killall sends a signal to all processes with an exact name match. Be cautious with these, especially killall, as you might terminate more than you intend.
For example, to kill all processes named heavy_computation.sh:
killall heavy_computation.sh
Or to send a SIGTERM signal to any process whose command line contains "computation":
pkill computation
The shell keeps track of background jobs using a job table, associating job numbers with PIDs. When you run a command with &, the shell forks a new process, places it in the background, and immediately returns control to you, registering the new process in its job table. fg and bg are shell built-ins that manipulate the terminal’s control of these processes, bringing them to the foreground or resuming them in the background. kill, pkill, and killall are external commands that send signals to processes via the operating system kernel, which then delivers those signals to the target process.
One subtle point is how standard input, output, and error are handled for background jobs. By default, they are still attached to your terminal. This means a background process writing to stdout or stderr will still print to your screen, potentially interleaving with your foreground commands. To truly isolate a background job, you often redirect its output:
./heavy_computation.sh > computation.log 2>&1 &
This redirects both standard output (>) and standard error (2>&1) to a file named computation.log, ensuring your terminal stays clean while the job runs.
Understanding how to manage these background jobs and signals is key to efficiently using the command line for any non-trivial task.
Next, you’ll likely want to explore how to manage jobs that have been stopped or are running in the background, and how to check their status more granularly using ps and grep.