Bash by Example: Kill Process
Sending signals to processes to terminate or modify behavior, understanding the difference between SIGTERM for graceful shutdown and SIGKILL for forceful termination, using kill, pkill, and killall commands, and following best practices to avoid data corruption.
Code
#!/bin/bash
# Start a dummy process
sleep 100 &
pid=$!
echo "Started sleep process (PID: $pid)"
# 1. Terminate gracefully (SIGTERM - 15)
# This is the default when no signal is specified
echo "Sending SIGTERM..."
kill $pid
# Check if it's gone
sleep 1
if ! ps -p $pid > /dev/null; then
echo "Process terminated."
fi
# Start another one
sleep 100 &
pid=$!
# 2. Force kill (SIGKILL - 9)
# Use this only if the process is stuck/unresponsive
echo "Sending SIGKILL..."
kill -9 $pid
echo "Process killed forcefully."Explanation
The kill command is somewhat misnamed; its primary purpose is to send signals to processes, not just to kill them. Signals are software interrupts that allow the operating system and users to communicate with running programs. While the default action is termination, signals can also request processes to reload configuration, pause execution, resume, or perform cleanup operations. The kernel maintains a signal table, and each signal has a number and a symbolic name (like SIGTERM or SIGKILL).
The two most critical signals for stopping processes are SIGTERM (Signal 15) and SIGKILL (Signal 9). SIGTERM is the polite approach—it asks the program to stop by sending an interrupt the process can catch. This gives the application a chance to execute signal handlers, save its state, flush buffers, close database connections, delete temporary files, and perform other cleanup tasks before exiting gracefully. Always try SIGTERM first using the default kill PID command.
SIGKILL (kill -9 PID) is the nuclear option. It is handled directly by the operating system kernel rather than the process itself, meaning the process cannot catch, ignore, or block it. The kernel immediately terminates the process and reclaims its memory, giving it no opportunity to clean up. This can lead to corrupted files, lost data, orphaned child processes, or locks that are never released. Use SIGKILL only when a process is completely unresponsive to SIGTERM or is stuck in an uninterruptible state. Related commands include pkill (kill by process name) and killall (kill all instances by exact name).
Code Breakdown
& operator launches sleep 100 in the background. We immediately capture its PID using $! for later use.kill $pid sends signal 15 (SIGTERM) by default. Most well-behaved programs will handle this gracefully and exit cleanly after cleanup.ps -p $pid. The ! negates the test, so the code runs if the process no longer exists.kill -9 $pid sends signal 9 (SIGKILL). This cannot be caught or ignored by the process. It is an immediate, forceful termination.
