3.3.2. Job Control, Signals, and Scheduling
💡 First Principle: Job control is the shell's mechanism for managing multiple processes in a single terminal session — pausing them, backgrounding them, and bringing them back to the foreground. Signals are the kernel's mechanism for sending asynchronous notifications to processes. They're related but distinct: job control uses signals internally (SIGSTOP, SIGCONT, SIGHUP), but signals can be sent to any process, not just shell jobs.
Signals — The Key Ones for XK0-006:
| Signal | Number | Default Action | Use Case |
|---|---|---|---|
| SIGHUP | 1 | Terminate | Reload config without restart (many daemons) |
| SIGINT | 2 | Terminate | Ctrl+C — user interrupt |
| SIGKILL | 9 | Terminate (force) | Last resort — bypasses handlers |
| SIGTERM | 15 | Terminate (graceful) | Default kill signal — preferred |
| SIGSTOP | 19 | Stop | Pause process (cannot be caught) |
| SIGCONT | 18 | Continue | Resume stopped process |
kill 1234 # Send SIGTERM (default) to PID 1234
kill -15 1234 # Explicit SIGTERM
kill -9 1234 # SIGKILL (force)
kill -1 1234 # SIGHUP (reload config)
kill -l # List all signal names and numbers
killall nginx # Send SIGTERM to all processes named nginx
pkill -u alice # Kill all processes owned by alice
pkill -SIGHUP nginx # Send SIGHUP to all nginx processes
Job Control:
./long_script.sh & # Start directly in background
Ctrl+Z # Suspend current foreground job (SIGSTOP)
bg # Resume suspended job in background
bg %2 # Resume job number 2 in background
fg # Bring most recent background job to foreground
fg %1 # Bring job 1 to foreground
jobs # List all jobs for current shell session
jobs -l # Include PIDs
nohup ./script.sh & # Run in background, immune to terminal close (SIGHUP)
nohup ./script.sh > output.log 2>&1 & # Capture output
nohup is essential for long-running commands started over SSH — without it, closing the SSH session sends SIGHUP to the shell, which propagates to child processes, killing your job.
Scheduling — cron, anacron, and at:
# crontab
crontab -e # Edit current user's crontab
crontab -l # List current user's crontab
crontab -r # Remove current user's crontab
crontab -u alice -e # Edit alice's crontab (root)
# Cron format: minute hour day-of-month month day-of-week command
# ┌───────── minute (0-59)
# │ ┌───────── hour (0-23)
# │ │ ┌───────── day of month (1-31)
# │ │ │ ┌───────── month (1-12)
# │ │ │ │ ┌───────── day of week (0-7, 0 and 7 = Sunday)
# │ │ │ │ │
0 2 * * * /usr/bin/backup.sh # Daily at 02:00
*/15 * * * * /usr/bin/check.sh # Every 15 minutes
0 0 1 * * /usr/bin/monthly.sh # First day of each month at midnight
# anacron — for systems not running 24/7 (runs missed jobs on next boot)
# Configuration: /etc/anacrontab
# Format: period delay job-id command
7 10 weekly-backup /usr/bin/backup.sh
# at — run once at a specific time
at 14:30 # Opens interactive prompt
at now + 2 hours # 2 hours from now
echo "/usr/bin/report.sh" | at midnight
atq # List pending at jobs
atrm 3 # Remove at job #3
Process Limits:
ulimit -a # Show all limits for current shell
ulimit -n 65536 # Set max open file descriptors (current session)
# Persistent limits: /etc/security/limits.conf
# alice hard nofile 65536
# alice soft nofile 32768
⚠️ Exam Trap: nohup alone does not background the process — it only prevents SIGHUP. You must also append & to actually run it in the background: nohup ./script.sh &. Without &, nohup still runs in the foreground and blocks your terminal.
Reflection Question: You start a long database backup over SSH: pg_dump mydb > backup.sql. Your SSH connection drops halfway through. The backup process is killed. What two changes to the command would prevent this from happening again?