Stage 2 · Tools
Process & System Management
Process Management
ps, kill, pkill, pgrep, nice, nohup, and job control for managing running processes.
Viewing Processes
ps is the primary tool for viewing processes. It shows process ID, parent process ID, CPU/memory usage, command, and state. Understanding ps output is essential for system administration.
# Show all processes for current user
ps aux
# Show process tree
ps auxf
# Find a specific process
ps aux | grep nginx
# Show process by name (no grep needed)
pgrep -la nginx
# Show specific fields
ps -eo pid,ppid,user,%cpu,%mem,comm --sort=-%cpu | head -20
# Watch processes in real-time
top -bn1 | head -20ps aux shows all processes with detailed information. The columns are: USER, PID, %CPU, %MEM, VSZ, RSS, TTY, STAT, START, TIME, COMMAND. Use --sort to order by CPU or memory.
pgrep -la nginx finds nginx processes without the extra grep process showing up in the output. pgrep is purpose-built for finding processes by name or pattern.
Killing Processes
kill sends signals to processes. The default signal is SIGTERM (15), which asks the process to terminate gracefully. SIGKILL (9) force-kills a process and cannot be caught.
# Graceful termination (default)
kill PID
# Force kill (last resort)
kill -9 PID
kill -KILL PID
# Send SIGHUP (reload config)
kill -HUP PID
# Kill by name
pkill nginx
# Kill all processes matching pattern
pkill -f "python.*server"
# List available signals
kill -lAlways try SIGTERM before SIGKILL. SIGTERM lets the process clean up open files, close connections, and save state. SIGKILL gives the process no chance to clean up.
SIGKILL (kill -9) does not let the process clean up. It can leave corrupted files, orphaned connections, or inconsistent state. Only use it as a last resort when SIGTERM does not work.
Background and Foreground
Bash lets you run commands in the background with & and manage them with job control commands. This is useful for long-running tasks that should not block your terminal.
# Run in background
long_task &
# Suspend current job (Ctrl+Z)
# Then move to background
bg
# List background jobs
jobs -l
# Bring job to foreground
fg %1
# Bring specific job to foreground
fg %2
# Disown a job (remove from job table)
disown %1Background jobs (&) run independently but still receive signals from the terminal. disown removes a job from the job table so it survives terminal closure.
Nice and Priority
nice adjusts a process's scheduling priority. Lower nice values mean higher priority. The default nice value is 0. The range is -20 (highest priority) to 19 (lowest priority).
# Run with low priority
nice -n 10 ./heavy_task.sh
# Run with high priority (requires root)
sudo nice -n -10 ./critical_task.sh
# Change priority of running process
renice 10 -p PID
# Show priority
ps -o pid,ni,comm -p PIDnice is essential for running background tasks without starving foreground processes. CPU-intensive tasks should run with nice +10 or higher to keep the system responsive.
nohup and Detaching
nohup makes a process immune to SIGHUP — the signal sent when the terminal closes. Combined with &, it lets processes survive terminal disconnection. For production, use screen, tmux, or systemd instead.
# nohup + background
nohup long_task.sh &
# Output goes to nohup.out by default
nohup long_task.sh > output.log 2>&1 &
# Using screen
screen -S mysession
# ... run commands ...
# Detach: Ctrl+A, D
# Reattach: screen -r mysession
# Using tmux
tmux new -s mysession
# ... run commands ...
# Detach: Ctrl+B, D
# Reattach: tmux attach -t mysessionnohup + & is the simplest way to detach a process. screen and tmux provide persistent sessions with reattachment capability. For long-running services, systemd is the proper solution.
Process Automation Patterns
These patterns combine process management tools for common automation scenarios.
# Wait for a process to complete
wait $PID
echo "Process $PID finished with exit code $?"
# Run with timeout
timeout 300 ./slow_task.sh # Kill after 5 minutes
# Restart a crashed process
while true; do
echo "Starting server..."
./server || echo "Server crashed, restarting..."
sleep 1
done
# Check if process is running
if pgrep -f "my_app" > /dev/null; then
echo "App is running"
else
echo "App is not running"
./start_app.sh
fiwait blocks until a background process finishes. timeout prevents runaway processes. The restart loop is a simple process supervisor pattern. pgrep checks process existence.
#!/usr/bin/env bash
set -euo pipefail
THRESHOLD=80
check_resources() {
local cpu_usage
cpu_usage=$(top -bn1 | grep "Cpu(s)" | awk '{print 100 - $8}')
local mem_usage
mem_usage=$(free | awk '/Mem:/ {printf "%.0f", $3/$2 * 100}')
if (( cpu_usage > THRESHOLD )); then
echo "WARNING: CPU usage at {cpu_usage}%"
fi
if (( mem_usage > THRESHOLD )); then
echo "WARNING: Memory usage at {mem_usage}%"
fi
}
check_resourcesThis script monitors CPU and memory usage and warns when thresholds are exceeded. It can be run periodically via cron or as part of a monitoring loop.
PID 1 (init/systemd) is the parent of all processes. Every process has a parent (PPID). If a parent dies, orphans are reparented to PID 1. Understanding this helps debug zombie processes and orphaned children.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.