Stage 3 · Build
Users, Permissions & Processes
Signals & Job Control
SIGTERM, SIGKILL, SIGHUP, fg, bg, jobs, nohup, and terminal session lifecycles.
Signal Overview
Signals are software interrupts sent to processes. They provide a mechanism for asynchronous communication between processes and the kernel.
| Signal | Number | Default Action | Description |
|---|---|---|---|
| SIGHUP | 1 | Terminate | Hangup (terminal closed) |
| SIGINT | 2 | Terminate | Interrupt (Ctrl+C) |
| SIGQUIT | 3 | Core dump | Quit (Ctrl+\) |
| SIGKILL | 9 | Terminate | Force kill (cannot catch) |
| SIGTERM | 15 | Terminate | Graceful termination |
| SIGSTOP | 19 | Stop | Pause (cannot catch) |
| SIGCONT | 18 | Continue | Resume stopped process |
| SIGUSR1 | 10 | Terminate | User-defined 1 |
| SIGUSR2 | 12 | Terminate | User-defined 2 |
Sending Signals
# Send SIGTERM (graceful shutdown)
kill 12345
kill -15 12345
kill -TERM 12345
# Send SIGKILL (force kill)
kill -9 12345
kill -KILL 12345
# Send SIGHUP (reload configuration)
kill -1 12345
kill -HUP 12345
# Send signal to process group
kill -9 -12345
# Negative PID = send to process group
# Send to all processes matching name
pkill -9 nginx
killall -9 nginx
# Send signal to process by name
pkill -HUP sshd
# Verify process received signal
kill -0 12345 # Check if process exists
echo $? # 0 = exists, 1 = doesn't existSIGTERM allows graceful cleanup. SIGKILL cannot be caught and terminates immediately. Always try SIGTERM before SIGKILL.
Signal Handling in Scripts
#!/usr/bin/env bash
set -euo pipefail
# Trap SIGTERM and SIGINT
trap 'echo "Received SIGTERM, cleaning up..."; cleanup; exit 0' TERM INT
trap 'echo "Received SIGHUP, reloading config..."; reload_config' HUP
trap '' HUP # Ignore SIGHUP
cleanup() {
rm -f "$TEMP_FILE"
kill "$BACKGROUND_PID" 2>/dev/null
echo "Cleanup complete"
}
TEMP_FILE=$(mktemp)
# Start background process
sleep 1000 &
BACKGROUND_PID=$!
echo "PID: $$"
echo "Waiting for signal..."
wait $BACKGROUND_PIDtrap lets you catch signals and perform cleanup. Always trap TERM and INT for graceful shutdown. trap '' HUP ignores SIGHUP.
Job Control
# Start background job
sleep 1000 &
# [1] 12345
# List jobs
jobs
# [1]+ Running sleep 1000 &
# Bring job to foreground
fg %1
# Send job to background (from foreground)
# Ctrl+Z to suspend, then:
bg %1
# Kill a job
kill %1
# Wait for background job to finish
wait
# Disown a job (remove from job table)
disown %1
# Job continues after terminal closesJob control lets you manage multiple processes in a terminal. fg brings to foreground, bg sends to background, disown removes from job table.
nohup and Background Jobs
# nohup: ignore SIGHUP (terminal close signal)
nohup long_running_task &
# Output goes to nohup.out
nohup long_running_task > output.log 2>&1 &
# Disown immediately
nohup long_running_task > output.log 2>&1 &
disown
# With screen/tmux (better approach)
screen -S mysession
# Run commands, then Ctrl+A D to detach
screen -r mysession
# With systemd (best for production)
systemd-run --unit=mytask --scope long_running_task
# Check if background job is still running
ps aux | grep long_running_tasknohup ignores SIGHUP so the job continues after logout. disown removes it from the shell's job table. For production, use systemd or screen/tmux.
Terminal Session Lifecycles
# Login shell vs non-login shell
# Login: reads /etc/profile, ~/.bash_profile, ~/.bash_login, ~/.profile
# Non-login: reads ~/.bashrc
# SIGHUP propagation
# When terminal closes:
# 1. Shell receives SIGHUP
# 2. Shell sends SIGHUP to all children
# 3. Children terminate unless they ignore SIGHUP
# Start a new session
setsid command # Creates new session, no terminal
nohup command & # Ignores SIGHUP, runs in background
# Check terminal association
tty # Shows current terminal
ps -p $$ -o tty # Shows shell's terminal
# Screen session management
screen -ls # List sessions
screen -r name # Reattach
screen -d -r name # Detach and reattachWhen a terminal closes, SIGHUP is sent to all processes in the session. Use nohup, disown, or screen/tmux to keep processes running after logout.
SIGTERM allows processes to clean up (close files, release locks, save state). SIGKILL terminates immediately without cleanup. Use SIGKILL only as a last resort.
Processes cannot catch or ignore SIGKILL. If a process does not respond to SIGTERM, check why before using SIGKILL. It may be stuck in uninterruptible sleep (D state).
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.