Introduction to kill
The kill command is a fundamental utility in Unix/Linux systems used to terminate or signal processes. Despite its name, kill doesn't just kill processes – it sends various signals to processes, allowing you to control their behavior. Understanding kill is essential for process management, system administration, and troubleshooting.
Basic Syntax
kill [options] <PID>... kill -l
What kill Does
- Sends signals to processes
- Terminates processes gracefully or forcefully
- Controls process behavior (pause, continue, reload, etc.)
- Lists available signals
1. Understanding Signals
What are Signals?
Signals are software interrupts sent to processes to notify them of events or request actions. Each signal has a specific meaning and default behavior.
Common Signals
| Signal | Number | Description | Default Action |
|---|---|---|---|
SIGHUP | 1 | Hangup detected | Terminate |
SIGINT | 2 | Interrupt (Ctrl+C) | Terminate |
SIGQUIT | 3 | Quit (Ctrl+) | Terminate with core dump |
SIGKILL | 9 | Kill (cannot be caught/ignored) | Terminate immediately |
SIGTERM | 15 | Termination (default kill) | Terminate |
SIGCONT | 18 | Continue if stopped | Continue execution |
SIGSTOP | 19 | Stop (cannot be caught/ignored) | Stop process |
SIGTSTP | 20 | Terminal stop (Ctrl+Z) | Stop process |
Listing Available Signals
# List all signals with numbers kill -l # List signals with names only kill -l | tr ' ' '\n' | grep -v '^$' # List specific signal kill -l 9 # Output: KILL # Get signal number from name kill -l KILL # Output: 9
2. Basic Usage
Finding Process IDs
# Find PID by process name pgrep firefox pidof firefox # Find PID with ps ps aux | grep firefox # Find all PIDs of a process pgrep -f "python script.py"
Sending Termination Signals
# Send SIGTERM (default, graceful termination) kill 1234 # Send specific signal by name kill -SIGTERM 1234 kill -TERM 1234 kill -15 1234 # Send SIGKILL (forceful, immediate termination) kill -9 1234 kill -SIGKILL 1234 kill -KILL 1234 # Kill multiple processes kill 1234 5678 9012 # Kill all processes with same name pkill firefox killall firefox
Examples
$ ps aux | grep firefox user 1234 5.2 2.1 2345678 123456 ? Sl 10:30 0:45 /usr/lib/firefox/firefox $ kill 1234 # Send SIGTERM $ kill -9 1234 # Force kill if SIGTERM doesn't work $ pgrep -f "python server.py" 5678 9012 $ kill -TERM 5678 9012 # Kill multiple
3. Signal Types and Their Uses
SIGTERM (15) - Graceful Termination
# Preferred way to terminate processes kill -15 1234 kill -TERM 1234 kill 1234 # Default is SIGTERM # Allows process to: # - Clean up resources # - Save state # - Close files properly # - Notify child processes
SIGKILL (9) - Forceful Termination
# Last resort when SIGTERM doesn't work kill -9 1234 kill -KILL 1234 # Process cannot ignore or handle this signal # No cleanup is performed # Use only when necessary
SIGHUP (1) - Hangup / Reload
# Reload configuration files (many daemons support this) kill -1 1234 kill -HUP 1234 # Examples: kill -HUP $(pgrep nginx) # Reload nginx configuration kill -HUP $(pgrep sshd) # Reload SSH daemon
SIGINT (2) - Interrupt
# Simulate Ctrl+C kill -2 1234 kill -INT 1234 # Useful for interrupting foreground processes
SIGSTOP (19) and SIGCONT (18)
# Pause a process kill -STOP 1234 kill -19 1234 # Check if process is stopped ps aux | grep 1234 # Process will show status 'T' (stopped) # Resume a stopped process kill -CONT 1234 kill -18 1234
4. Advanced Usage
Killing Process Trees
# Kill process and all its children kill -TERM -1234 # Negative PID kills process group # Using pkill with process groups pkill -TERM -g 1234 # Find and kill process tree pstree -p 1234 | grep -oP '\d+' | xargs kill -9 # Kill entire process group kill -- -$(ps -o pgid= -p 1234 | grep -o '[0-9]*')
Using pkill and pgrep
# pkill - kill processes by name pkill firefox pkill -f "python script.py" # Match full command line pkill -u username # Kill all processes of user pkill -t pts/0 # Kill all processes in terminal # pgrep - find processes by name pgrep firefox pgrep -u username -l # List with names pgrep -f "python.*server" # Regex matching # Combined example pkill -TERM -u $(whoami) python
Using killall
# Kill all processes with given name killall firefox killall -9 chrome killall -u username # Kill all processes of user # Case-insensitive matching killall -I FIREFOX # Wait for processes to die killall -w firefox # Wait until all firefox processes are gone # Interactive confirmation killall -i firefox # Ask before killing each process
5. Practical Examples
Script Examples
Process Monitor and Killer:
#!/bin/bash
# proc_killer.sh - Monitor and kill processes by resource usage
KILL_THRESHOLD_CPU=90
KILL_THRESHOLD_MEM=95
CHECK_INTERVAL=10
EXEMPT_PIDS="1 2 3" # Never kill these PIDs
check_and_kill() {
local pid=$1
local cpu=$2
local mem=$3
local name=$4
for exempt in $EXEMPT_PIDS; do
if [[ $pid -eq $exempt ]]; then
return
fi
done
if (( $(echo "$cpu > $KILL_THRESHOLD_CPU" | bc -l) )); then
echo "Killing process $pid ($name) - CPU usage: $cpu%"
kill -TERM "$pid"
sleep 2
if kill -0 "$pid" 2>/dev/null; then
echo "Process still running, using SIGKILL"
kill -9 "$pid"
fi
elif (( $(echo "$mem > $KILL_THRESHOLD_MEM" | bc -l) )); then
echo "Killing process $pid ($name) - Memory usage: $mem%"
kill -TERM "$pid"
fi
}
while true; do
ps aux | tail -n +2 | while read -r line; do
pid=$(echo "$line" | awk '{print $2}')
cpu=$(echo "$line" | awk '{print $3}')
mem=$(echo "$line" | awk '{print $4}')
name=$(echo "$line" | awk '{for(i=11;i<=NF;i++) printf "%s ", $i}')
check_and_kill "$pid" "$cpu" "$mem" "$name"
done
sleep $CHECK_INTERVAL
done
Graceful Shutdown Script:
#!/bin/bash
# graceful_shutdown.sh - Shut down processes gracefully
SHUTDOWN_TIMEOUT=30
PROCESSES=("nginx" "postgresql" "redis-server")
shutdown_process() {
local proc=$1
local pids=$(pgrep -f "$proc")
if [[ -z "$pids" ]]; then
echo "No $proc processes running"
return
fi
echo "Shutting down $proc (PIDs: $pids)"
# Send SIGTERM to all processes
for pid in $pids; do
kill -TERM "$pid"
done
# Wait for processes to terminate
local waited=0
while [[ $waited -lt $SHUTDOWN_TIMEOUT ]]; do
local remaining=""
for pid in $pids; do
if kill -0 "$pid" 2>/dev/null; then
remaining="$remaining $pid"
fi
done
if [[ -z "$remaining" ]]; then
echo "$proc shutdown successfully"
return 0
fi
sleep 1
((waited++))
done
# Force kill remaining processes
echo "$proc still running after $SHUTDOWN_TIMEOUT seconds, forcing kill"
for pid in $remaining; do
kill -9 "$pid" 2>/dev/null
done
}
# Shut down all processes
for proc in "${PROCESSES[@]}"; do
shutdown_process "$proc"
done
echo "All processes shut down"
Process Tree Killer:
#!/bin/bash
# kill_tree.sh - Kill a process and all its children
kill_tree() {
local parent_pid=$1
local signal=${2:-TERM}
# Get all child PIDs
local children=$(pgrep -P "$parent_pid")
# Recursively kill children first
for child in $children; do
kill_tree "$child" "$signal"
done
# Kill the parent
if kill -0 "$parent_pid" 2>/dev/null; then
echo "Killing $parent_pid with signal $signal"
kill -"$signal" "$parent_pid"
fi
}
# Function to kill process tree with timeout
kill_tree_timeout() {
local parent_pid=$1
local timeout=${2:-10}
# Try graceful termination first
kill_tree "$parent_pid" TERM
# Wait for processes to die
local waited=0
while [[ $waited -lt $timeout ]]; do
if ! kill -0 "$parent_pid" 2>/dev/null; then
echo "Process tree terminated successfully"
return 0
fi
sleep 1
((waited++))
done
# Force kill if still running
echo "Timeout reached, forcing kill"
kill_tree "$parent_pid" KILL
}
# Main script
if [[ $# -lt 1 ]]; then
echo "Usage: $0 <parent_pid> [timeout]"
exit 1
fi
kill_tree_timeout "$1" "${2:-10}"
6. Signal Handling in Scripts
Trapping Signals
#!/bin/bash
# trap_example.sh - Demonstrating signal trapping
cleanup() {
echo "Cleaning up temporary files..."
rm -f /tmp/temp_*
echo "Exiting gracefully"
exit 0
}
handle_interrupt() {
echo "Received interrupt signal (Ctrl+C)"
cleanup
}
handle_terminate() {
echo "Received termination signal"
cleanup
}
handle_hangup() {
echo "Received hangup signal, reloading configuration"
# Reload configuration logic here
}
# Set traps for various signals
trap handle_interrupt SIGINT SIGTERM
trap handle_hangup SIGHUP
trap cleanup EXIT
echo "Process $$ running. PID: $$"
echo "Press Ctrl+C to test interrupt"
echo "Send signals: kill -HUP $$ for reload"
# Simulate work
while true; do
echo "Working..."
sleep 2
done
Checking if Process Exists
# Check if process is running
if kill -0 1234 2>/dev/null; then
echo "Process 1234 is running"
else
echo "Process 1234 is not running"
fi
# Wait for process to end
while kill -0 1234 2>/dev/null; do
echo "Waiting for process 1234 to terminate..."
sleep 1
done
# Function to check process
is_running() {
kill -0 "$1" 2>/dev/null
return $?
}
7. Process Groups and Sessions
Understanding Process Groups
# Show process groups ps -eo pid,pgid,cmd | head -10 # Kill entire process group kill -TERM -1234 # Negative PID = process group # Find process group of a process ps -o pgid= -p 1234 # Kill all processes in same group as PID kill -TERM -- -$(ps -o pgid= -p 1234 | tr -d ' ')
Job Control
# Start a background job long_running_command & # List jobs jobs # Bring job to foreground fg %1 # Send job to background bg %1 # Kill job by job number kill %1 kill -9 %2
8. Security Considerations
Permissions
# Can only kill your own processes (unless root) kill 1 # Cannot kill init process as normal user # Output: bash: kill: (1) - Operation not permitted # Check process ownership ps -o user= -p 1234 # Root can kill any process sudo kill -9 1234
Safe Killing Practices
# Always try SIGTERM first kill -TERM 1234 # Wait a bit sleep 5 # Check if still running if kill -0 1234 2>/dev/null; then echo "Process still running, using SIGKILL" kill -9 1234 fi # Never kill critical system processes # Process 1 (init/systemd) - don't kill! # Kernel processes (usually in [brackets]) - don't kill!
9. Monitoring and Logging
Logging Killed Processes
#!/bin/bash
# kill_logger.sh - Log all kill commands
LOG_FILE="/var/log/kill_monitor.log"
# Function to log kills
log_kill() {
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
local user=$(whoami)
local pid=$1
local signal=$2
local process_info=$(ps -p "$pid" -o comm= 2>/dev/null)
echo "$timestamp - User: $user - PID: $pid - Signal: $signal - Process: $process_info" >> "$LOG_FILE"
}
# Override kill command
kill() {
local pid=$1
local signal=${2:-TERM}
# Log the kill attempt
log_kill "$pid" "$signal"
# Execute real kill
command kill "$@"
}
# Example usage
kill 1234
kill -9 5678
Audit Trail
# Check audit logs for kill commands sudo ausearch -m task -c kill # Check process history lastcomm | grep kill # Monitor kill commands with auditd sudo auditctl -a exit,always -S kill
10. Troubleshooting
Common Issues
# Process won't die kill -9 1234 # Still running? # Check if process is zombie ps aux | grep 1234 # Zombie shows as 'Z' in STAT column # Permission denied kill 1234 # Error: Operation not permitted # Check ownership and try with sudo # No such process kill 1234 # Error: No such process # Process already terminated # Signal number out of range kill -100 1234 # Error: Invalid signal # Check valid signals with kill -l
Debugging
# Trace system calls for kill strace -e kill kill 1234 # Check signal handling of process cat /proc/1234/status | grep -i sig # See pending signals ps -o pending= -p 1234 # Monitor signals to process kill -CONT 1234
11. Integration with Other Commands
Using with ps
# Kill processes by pattern
ps aux | grep python | awk '{print $2}' | xargs kill -9
# Kill processes older than certain time
ps -eo pid,etime,cmd | grep "python" | awk '$2 ~ /[0-9]+-[0-9]+:[0-9]+/ {print $1}' | xargs kill
# Kill processes with specific state
ps -eo pid,stat,cmd | grep "^ *[0-9]\+ Z" | awk '{print $1}' | xargs kill -9 # Kill zombies
Using with find
# Kill processes using specific files
lsof /path/to/file | tail -n +2 | awk '{print $2}' | xargs kill -9
# Kill processes in specific directory
find /proc -maxdepth 1 -type d -name "[0-9]*" 2>/dev/null | \
while read proc; do
if readlink "$proc/cwd" | grep -q "/target/dir"; then
kill -9 $(basename "$proc")
fi
done
Using with systemctl (systemd)
# For system services, use systemctl instead of kill sudo systemctl stop nginx sudo systemctl kill nginx # Sends SIGKILL to all processes of service sudo systemctl kill -s HUP nginx # Send specific signal
12. Signal Table Reference
Complete Signal List
| # | Name | Description | Default Action |
|---|---|---|---|
| 1 | SIGHUP | Hangup detected | Terminate |
| 2 | SIGINT | Interrupt from keyboard | Terminate |
| 3 | SIGQUIT | Quit from keyboard | Core dump |
| 4 | SIGILL | Illegal instruction | Core dump |
| 5 | SIGTRAP | Trace/breakpoint trap | Core dump |
| 6 | SIGABRT | Abort signal | Core dump |
| 7 | SIGBUS | Bus error | Core dump |
| 8 | SIGFPE | Floating point exception | Core dump |
| 9 | SIGKILL | Kill signal | Terminate |
| 10 | SIGUSR1 | User-defined signal 1 | Terminate |
| 11 | SIGSEGV | Invalid memory reference | Core dump |
| 12 | SIGUSR2 | User-defined signal 2 | Terminate |
| 13 | SIGPIPE | Broken pipe | Terminate |
| 14 | SIGALRM | Timer signal | Terminate |
| 15 | SIGTERM | Termination signal | Terminate |
| 16 | SIGSTKFLT | Stack fault | Terminate |
| 17 | SIGCHLD | Child stopped or terminated | Ignore |
| 18 | SIGCONT | Continue if stopped | Continue |
| 19 | SIGSTOP | Stop process | Stop |
| 20 | SIGTSTP | Stop typed at terminal | Stop |
| 21 | SIGTTIN | Terminal input for background | Stop |
| 22 | SIGTTOU | Terminal output for background | Stop |
| 23 | SIGURG | Urgent condition on socket | Ignore |
| 24 | SIGXCPU | CPU time limit exceeded | Core dump |
| 25 | SIGXFSZ | File size limit exceeded | Core dump |
| 26 | SIGVTALRM | Virtual alarm clock | Terminate |
| 27 | SIGPROF | Profiling timer expired | Terminate |
| 28 | SIGWINCH | Window resize signal | Ignore |
| 29 | SIGIO | I/O now possible | Terminate |
| 30 | SIGPWR | Power failure | Terminate |
| 31 | SIGSYS | Bad system call | Core dump |
13. Best Practices
Kill Command Best Practices
- Always try SIGTERM first:
kill -TERM 1234 sleep 5 kill -0 1234 2>/dev/null && kill -9 1234
- Check process ownership:
if [[ $(ps -o user= -p 1234) == "$USER" ]]; then kill 1234 else sudo kill 1234 fi
- Verify process exists:
if kill -0 1234 2>/dev/null; then kill -TERM 1234 else echo "Process 1234 not running" fi
- Use process groups for related processes:
kill -TERM -1234 # Kill entire process group
- Log important kills:
logger "Killing process 1234 (high CPU usage)" kill -9 1234
Safety Checklist
- [ ] Is this my process or do I have permission?
- [ ] Is this a critical system process?
- [ ] Have I tried SIGTERM before SIGKILL?
- [ ] Are there dependent services that might be affected?
- [ ] Have I saved all important data?
- [ ] Do I have the correct PID?
- [ ] Is there a more graceful shutdown method available?
14. Quick Reference Card
Common Kill Commands
| Command | Description |
|---|---|
kill 1234 | Send SIGTERM to PID 1234 |
kill -9 1234 | Send SIGKILL to PID 1234 |
kill -TERM 1234 | Send SIGTERM by name |
kill -SIGKILL 1234 | Send SIGKILL by full name |
kill -l | List all signals |
kill -l 9 | Get name of signal 9 |
killall firefox | Kill all firefox processes |
pkill -f "python script" | Kill processes matching pattern |
pgrep firefox | Find firefox PIDs |
kill -STOP 1234 | Suspend process |
kill -CONT 1234 | Resume process |
kill -HUP 1234 | Hangup/reload process |
Signal Quick Reference
| Signal | Number | Use Case |
|---|---|---|
| SIGTERM | 15 | Graceful termination (default) |
| SIGKILL | 9 | Forceful termination (last resort) |
| SIGHUP | 1 | Reload configuration |
| SIGINT | 2 | Interrupt (Ctrl+C) |
| SIGSTOP | 19 | Suspend process |
| SIGCONT | 18 | Resume suspended process |
| SIGUSR1 | 10 | User-defined action |
| SIGUSR2 | 12 | User-defined action |
Exit Codes
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | Failure (unspecified) |
| 2 | Invalid option |
| 64 | Invalid signal specification |
| 65 | Process not found |
Conclusion
The kill command is essential for process management in Unix/Linux systems:
Key Points Summary
- Signals:
killsends signals, not just termination requests - Default Signal: SIGTERM (15) - graceful termination
- Force Kill: SIGKILL (9) - immediate termination (last resort)
- Process Groups: Use negative PIDs to kill process groups
- Permissions: Can only kill your own processes (except root)
- Signal Handling: Processes can trap and handle many signals
- Multiple Tools:
kill,pkill,killallfor different use cases
Best Practices
- Always try SIGTERM first - Allow processes to clean up
- Use SIGKILL only when necessary - It doesn't allow cleanup
- Verify PIDs - Ensure you're killing the right process
- Check permissions - Use sudo when needed
- Consider dependencies - Killing one process may affect others
- Log important kills - For audit and troubleshooting
- Use process groups - For related processes
Quick Reference
| Situation | Command |
|---|---|
| Normal termination | kill 1234 |
| Force termination | kill -9 1234 |
| Reload config | kill -HUP 1234 |
| Suspend process | kill -STOP 1234 |
| Resume process | kill -CONT 1234 |
| Kill by name | pkill firefox |
| Kill all with name | killall firefox |
| List signals | kill -l |
| Check if running | kill -0 1234 |
The kill command's versatility in sending different signals makes it an indispensable tool for process control, from graceful shutdowns to forceful terminations and everything in between.