Foreground vs Background Processes (fg, bg, jobs, kill)

Mastering foreground and background process management is essential for efficient Linux multitasking. Understanding how to control job execution, switch between tasks, and properly terminate processes enables you to work productively while maintaining system stability. This guide covers the complete workflow from starting processes to managing their lifecycle.

Foreground vs Background: Key Differences

Aspect Foreground Processes Background Processes
Control Interactive, controls terminal Non-interactive, runs independently
Input/Output Uses stdin/stdout/stderr No terminal I/O (unless redirected)
Shell Access Shell waits for completion Shell prompt returns immediately
Termination Ctrl+C (SIGINT) kill command required
Suspension Ctrl+Z (SIGTSTP) Not applicable
Use Case Interactive tasks, editing Long-running tasks, services
Quick Reference:
Foreground - Process controls terminal, you wait for it
Background - Process runs independently, you get prompt back
• Use & to start in background
• Use Ctrl+Z then bg to move to background
• Use fg to bring to foreground

Job Control Workflow

Complete Job Management Cycle

Start Process
Ctrl+Z
jobs
bg/fg
kill

Essential Job Control Commands

💼
jobs

List current shell jobs with their status and job numbers.

jobs [options]

Common Options:

  • jobs - Basic job list
  • jobs -l - With PIDs
  • jobs -p - PIDs only
  • jobs -r - Running jobs only
  • jobs -s - Stopped jobs only

Job Status Indicators:

  • + - Default job for fg/bg
  • - - Previous default job
  • Running - Executing in background
  • Stopped - Suspended
  • Done - Completed
⏸️
Ctrl+Z

Suspend foreground process and return to shell prompt.

Press Ctrl+Z while process is running

What Happens:

  • Sends SIGTSTP signal
  • Process stops execution
  • Shell prompt returns
  • Job appears as "Stopped" in jobs list
  • Process state preserved

Example:

$ sleep 100
# Press Ctrl+Z
[1]+  Stopped                 sleep 100
$ jobs
[1]+  Stopped                 sleep 100
🔁
bg

Resume suspended job in background.

bg [%job_number]

Usage:

  • bg - Resume most recent job
  • bg %1 - Resume job 1 specifically
  • bg %sleep - Resume job containing "sleep"

Example:

$ sleep 100
^Z
[1]+  Stopped                 sleep 100
$ bg
[1]+ sleep 100 &
$ jobs
[1]+  Running                 sleep 100 &
▶️
fg

Bring background job to foreground.

fg [%job_number]

Usage:

  • fg - Bring most recent job to foreground
  • fg %1 - Bring job 1 to foreground
  • fg %vim - Bring vim job to foreground

Example:

$ jobs
[1]   Running                 sleep 100 &
[2]   Stopped                 vim file.txt
$ fg %2
# Now editing file.txt in foreground
🚪
& (ampersand)

Start command directly in background.

command &

Features:

  • Immediate shell prompt return
  • Job number and PID displayed
  • Appears in jobs list
  • Output may mix with foreground (use redirection)

Examples:

  • sleep 100 &
  • ./script.sh > output.log 2>&1 &
  • tar -czf backup.tar.gz /data &
🔒
disown

Remove job from shell's job table.

disown [%job_number]

Purpose:

  • Detach job from shell session
  • Job survives shell exit
  • No longer appears in jobs list
  • Ideal for long-running tasks

Example:

$ sleep 1000 &
[1] 1234
$ disown %1
$ jobs
# No jobs listed
# Process continues running even if shell exits

Process Termination with kill

Signal Number Keyboard Purpose Usage
SIGINT 2 Ctrl+C Interrupt foreground process Graceful termination
SIGTSTP 20 Ctrl+Z Suspend foreground process Stop for bg/fg
SIGTERM 15 - Termination signal (default) kill PID
SIGKILL 9 - Force termination kill -9 PID
SIGCONT 18 - Continue stopped process kill -CONT PID
💀
kill

Send signals to processes for termination or control.

kill [options] PID
kill [options] %job_number

Common Usage:

  • kill 1234 - Send SIGTERM (graceful)
  • kill -9 1234 - Send SIGKILL (force)
  • kill %1 - Kill job 1
  • kill -STOP 1234 - Stop process
  • kill -CONT 1234 - Continue process
🎯

Kill Alternatives

Other commands for process termination.

pkill | killall

Pattern-based Killing:

  • pkill process_name - Kill by name
  • pkill -f "pattern" - Kill by full command
  • killall process_name - Kill all matching
  • pkill -u username - Kill user's processes

Examples:

  • pkill firefox
  • pkill -f "python script.py"
  • killall chrome

Practical Job Control Examples

Real-World Job Management Scenarios

# 1. Basic Job Control Workflow
# Start a long-running process
sleep 300

# Suspend it with Ctrl+Z
^Z
[1]+  Stopped                 sleep 300

# Check jobs
jobs -l
[1]+  1234 Stopped                 sleep 300

# Resume in background
bg
[1]+ sleep 300 &

# Bring back to foreground
fg
sleep 300

# Terminate with Ctrl+C
^C

# 2. Direct Background Execution
# Start multiple background jobs
sleep 100 &
[1] 1234
sleep 200 &
[2] 1235
sleep 300 &
[3] 1236

# List all jobs
jobs
[1]   Running                 sleep 100 &
[2]   Running                 sleep 200 &
[3]   Running                 sleep 300 &

# Kill specific job
kill %2
[2]   Terminated              sleep 200

# 3. Advanced Job Management
# Start process with output redirection
./server.sh > server.log 2>&1 &
[1] 1234

# Disown to survive shell exit
disown %1

# Check if still running
ps -p 1234

# 4. Interactive Program Management
# Start text editor
vim document.txt

# Suspend to run commands
Ctrl+Z
[1]+  Stopped                 vim document.txt

# Run some commands
ls -la
cat file.txt

# Resume editing
fg

# 5. Process Monitoring and Control
# Find process PID
pgrep nginx
1234

# Graceful termination
kill 1234

# Force termination if needed
kill -9 1234

# Stop process temporarily
kill -STOP 1234

# Resume process
kill -CONT 1234

# 6. Batch Job Management
# Start multiple data processing jobs
./process_data.sh file1.csv &
./process_data.sh file2.csv &
./process_data.sh file3.csv &

# Monitor progress
jobs
[1]   Running                 ./process_data.sh file1.csv &
[2]   Running                 ./process_data.sh file2.csv &
[3]   Running                 ./process_data.sh file3.csv &

# Wait for all to complete
wait

# 7. Service-like Background Jobs
# Start with nohup for persistence
nohup ./long_task.sh > task.log 2>&1 &

# Disown to detach from shell
disown

# Job continues running indefinitely

Common Use Cases

Development Workflow

  • Code Editing: vim file.pyCtrl+Z → run tests → fg
  • Build Processes: make & → continue working → check jobs
  • Testing: ./test_suite.sh & → monitor with tail -f test.log

System Administration

  • Backup Operations: tar -czf backup.tar.gz /data &
  • Service Management: ./start_service.sh & then disown
  • Monitoring: tail -f /var/log/syslogCtrl+Z → investigate → fg

Data Processing

  • Batch Jobs: Multiple process_file.sh & commands
  • Long-running Tasks: nohup ./analysis.py > results.log 2>&1 &
  • Pipeline Management: Chain processes with proper job control

Advanced Techniques

🛡️

nohup for Persistent Jobs

Run commands immune to hangup signals.

nohup command [args] &

Features:

  • Immune to SIGHUP (terminal disconnect)
  • Output redirected to nohup.out
  • Continues running after shell exit
  • Combine with & for background

Example:

nohup ./server.sh > server.log 2>&1 &
⏱️

wait for Job Completion

Wait for background jobs to complete.

wait [%job_number]

Usage:

  • wait - Wait for all background jobs
  • wait %1 - Wait for job 1 specifically
  • Useful in scripts for synchronization

Example:

./job1.sh &
./job2.sh &
./job3.sh &
wait  # Wait for all three jobs
echo "All jobs completed"
🎛️

Terminal Multiplexers

Advanced session management tools.

screen | tmux

Benefits:

  • Persistent sessions
  • Multiple virtual terminals
  • Session sharing
  • Detach and reattach

Basic Usage:

  • screen - Start new session
  • Ctrl+A D - Detach from screen
  • screen -r - Reattach to session
Important Considerations:
• Background jobs terminate when shell exits (unless disowned or using nohup)
• Use kill -9 only as last resort - it doesn't allow graceful cleanup
• Be careful with pkill and killall - they can match multiple processes
• Suspended jobs still consume system resources
• Always check job status before assuming completion
• Use output redirection to prevent background job output from mixing with terminal
Pro Tips:
• Use jobs -l to see PIDs for use with other commands
• Combine nohup with output redirection for production services
• Use wait in scripts to synchronize parallel tasks
• Remember that Ctrl+Z stops while Ctrl+C terminates
• Use disown after starting a job to make it persistent
• Consider screen or tmux for complex multitasking

Key Takeaways

Mastering foreground and background process management transforms your Linux workflow from linear to multidimensional. By understanding when to use foreground execution for interactive tasks and background execution for long-running processes, you can significantly improve your productivity. The jobs, fg, bg, and kill commands provide complete control over your shell's job table, while tools like nohup and disown enable persistent execution. Remember that proper job control not only makes you more efficient but also helps maintain system stability by ensuring processes are properly managed throughout their lifecycle.

Next Step: Explore system monitoring and performance analysis to understand how to track system resources, identify bottlenecks, and optimize process execution for better overall system performance.