← Back to Bash Course | Chapter 11: Process Management | Lesson 12 of 12

Killing Processes

The kill command sends a signal to a process, usually asking it to stop, and a process can respond to that request differently depending on which signal was sent.

Sending the Default Signal

kill pid without a signal name sends SIGTERM, a polite termination request that a process can trap and respond to before actually exiting, unlike a forceful kill.

Example: Sending the Default Signal

bash
#!/bin/bash
sleep 5 &
pid=$!
kill "$pid"
wait "$pid" 2>/dev/null
echo "background sleep was asked to terminate, wait returned status $?"

Checking Before You Kill

kill -0 pid sends no actual signal but checks whether the process exists and is signalable, returning a normal exit status; this avoids errors from trying to kill an already-finished job.

Example: Checking Before You Kill

bash
#!/bin/bash
sleep 0.2 &
pid=$!
if kill -0 "$pid" 2>/dev/null; then
    echo "process $pid is still running"
fi
wait "$pid"
if ! kill -0 "$pid" 2>/dev/null; then
    echo "process $pid is no longer running"
fi

Forceful Termination with SIGKILL

kill -9 pid (SIGKILL) cannot be caught, blocked, or ignored by the target process, so it always terminates it immediately, but the process has no opportunity to run its own cleanup code.

Note: Reserve SIGKILL for processes that ignore a normal SIGTERM request, since it skips any cleanup the process might have wanted to run.

Example: Forceful Termination with SIGKILL

bash
#!/bin/bash
sleep 5 &
pid=$!
kill -9 "$pid"
wait "$pid" 2>/dev/null
status=$?
echo "exit status after SIGKILL: $status"

Understanding Signal-Based Exit Codes

When a process is terminated by a signal instead of exiting normally, its reported exit status is conventionally 128 plus the signal's number (for example, SIGTERM is 15, so a terminated process often reports 143). Note $BASHPID (the actual subshell's PID) is used here rather than $$, since $$ always refers to the original top-level shell even inside a subshell.

Warning: Sending SIGTERM to $$ instead of $BASHPID from inside a subshell would terminate the whole script, not just the subshell.

Example: Understanding Signal-Based Exit Codes

bash
#!/bin/bash
( kill -TERM $BASHPID ) &
sub_pid=$!
wait "$sub_pid"
echo "the subshell that sent itself SIGTERM reported status: $?"
Common Mistakes
  1. Assuming kill always forcefully terminates a process instantly; by default it sends SIGTERM, a polite request the target can catch and ignore or clean up before honoring.
  2. Forgetting kill -9 (SIGKILL) cannot be caught, blocked, or ignored, which is powerful but also means the target gets no chance to clean up.
  3. Not checking whether a background job already finished before trying to kill it, which produces an error like "no such process".
Chapter Summary
  • kill pid sends SIGTERM by default, a request that a well-behaved process can catch and act on before exiting.
  • kill -9 pid (SIGKILL) terminates unconditionally and cannot be caught or ignored by the target.
  • A process killed by signal N conventionally reports an exit status of 128 + N to its parent.
  • Checking whether a PID is still running (e.g. with ps -p or kill -0) before signaling it avoids "no such process" errors.

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.