ZetCode

Linux kill Command

last modified October 23, 2026

The kill command in Linux sends signals to processes. Despite its name, it does not only terminate programs: signals also ask a process to reload its configuration, pause, resume, or perform a custom action. By default, kill sends SIGTERM, a polite request to terminate.

In Bash, kill is a shell builtin, which also accepts job specifications such as %1; a standalone /bin/kill program from the procps-ng package exists as well. Related tools pgrep and pkill find and signal processes by name. A regular user can send signals only to their own processes; root can signal any process.

Terminating a process by PID

Every process has a process ID (PID). We start a background process, find its PID with pgrep, and terminate it.

sleep 300 &
pgrep -a sleep
kill $(pgrep sleep)

The -a option of pgrep prints the full command line next to the PID. The command substitution passes the PID to kill, which sends SIGTERM. Afterwards, pgrep finds no matching process and exits with a non-zero status. The ps aux or top commands can be used to look up PIDs as well.

$ sleep 300 &
$ pgrep -a sleep
11 sleep 300
$ kill $(pgrep sleep)
$ pgrep -a sleep || echo "no sleep process"
no sleep process

Listing signals

The -l option lists the signal names and numbers or translates between them.

kill -l
kill -l 15
kill -l KILL

The most frequently used signals are SIGHUP (1), SIGINT (2, sent by Ctrl+C), SIGKILL (9), SIGTERM (15), SIGSTOP (19), and SIGCONT (18). Signal numbers can differ between architectures, so names are more portable.

$ kill -l
 1) SIGHUP	 2) SIGINT	 3) SIGQUIT	 4) SIGILL	 5) SIGTRAP
 6) SIGABRT	 7) SIGBUS	 8) SIGFPE	 9) SIGKILL	10) SIGUSR1
11) SIGSEGV	12) SIGUSR2	13) SIGPIPE	14) SIGALRM	15) SIGTERM
16) SIGSTKFLT	17) SIGCHLD	18) SIGCONT	19) SIGSTOP	20) SIGTSTP
21) SIGTTIN	22) SIGTTOU	23) SIGURG	24) SIGXCPU	25) SIGXFSZ
26) SIGVTALRM	27) SIGPROF	28) SIGWINCH	29) SIGIO	30) SIGPWR
31) SIGSYS	34) SIGRTMIN	35) SIGRTMIN+1	36) SIGRTMIN+2	37) SIGRTMIN+3
38) SIGRTMIN+4	39) SIGRTMIN+5	40) SIGRTMIN+6	41) SIGRTMIN+7	42) SIGRTMIN+8
43) SIGRTMIN+9	44) SIGRTMIN+10	45) SIGRTMIN+11	46) SIGRTMIN+12	47) SIGRTMIN+13
48) SIGRTMIN+14	49) SIGRTMIN+15	50) SIGRTMAX-14	51) SIGRTMAX-13	52) SIGRTMAX-12
53) SIGRTMAX-11	54) SIGRTMAX-10	55) SIGRTMAX-9	56) SIGRTMAX-8	57) SIGRTMAX-7
58) SIGRTMAX-6	59) SIGRTMAX-5	60) SIGRTMAX-4	61) SIGRTMAX-3	62) SIGRTMAX-2
63) SIGRTMAX-1	64) SIGRTMAX	
$ kill -l 15
TERM
$ kill -l KILL
9

Specifying the signal

A signal can be given by name, with or without the SIG prefix, or by number.

kill -s TERM $pid
kill -SIGTERM $pid
kill -15 $pid

All three forms send SIGTERM. The $! variable holds the PID of the most recent background process, which we store in pid. In the end, no sleep process is left.

$ sleep 301 & pid=$!
$ kill -s TERM $pid
$ sleep 302 & pid=$!
$ kill -SIGTERM $pid
$ sleep 303 & pid=$!
$ kill -15 $pid
$ pgrep -c sleep
0

Handling signals in a script

A process can catch most signals and react to them. In Bash, the trap builtin installs signal handlers.

worker.sh
#!/bin/bash

trap 'echo "worker: received SIGTERM, cleaning up"; rm -f /tmp/worker.lock; exit 0' TERM
trap 'echo "worker: received SIGHUP, reloading configuration"' HUP
trap 'echo "worker: received SIGUSR1, processed $count items"' USR1

touch /tmp/worker.lock
count=0

while true; do
    count=$((count + 1))
    sleep 0.1
done

The worker handles SIGHUP, which daemons traditionally use as a request to reload their configuration, and SIGUSR1, a user-defined signal with an application-specific meaning; here it reports progress. On SIGTERM, it removes its lock file before exiting. This graceful shutdown is why SIGTERM should be tried first.

$ ./worker.sh > worker.log & pid=$!
$ kill -HUP $pid
$ kill -USR1 $pid
$ kill $pid
$ cat worker.log
worker: received SIGHUP, reloading configuration
worker: received SIGUSR1, processed 8 items
worker: received SIGTERM, cleaning up
$ ls /tmp/worker.lock
ls: cannot access '/tmp/worker.lock': No such file or directory

Forcing termination with SIGKILL

A process may ignore SIGTERM. The SIGKILL signal cannot be caught or ignored; the kernel terminates the process immediately.

stubborn.sh
#!/bin/bash

trap 'echo "stubborn: ignoring SIGTERM"' TERM

while true; do
    sleep 0.1
done

The script catches SIGTERM and keeps running, as ps confirms. After kill -9, ps prints only the header line because the process no longer exists. Since the process gets no chance to clean up, temporary files, locks, or partially written data may be left behind. A process in the uninterruptible sleep state (D), typically waiting for I/O, does not react even to SIGKILL until the operation finishes.

$ ./stubborn.sh > stubborn.log & pid=$!
$ kill $pid
$ cat stubborn.log
stubborn: ignoring SIGTERM
$ ps -o pid,stat,cmd -p $pid
    PID STAT CMD
     45 S    /bin/bash ./stubborn.sh
$ kill -9 $pid
$ ps -o pid,stat,cmd -p $pid
    PID STAT CMD

Terminating multiple processes

kill accepts several PIDs at once.

kill $a $b $c

We start three background processes, store their PIDs, and terminate them with a single command.

$ sleep 401 & a=$!; sleep 402 & b=$!; sleep 403 & c=$!
$ pgrep -c sleep
3
$ kill $a $b $c
$ pgrep -c sleep
0

Checking if a process exists

Signal 0 is not delivered at all; kill only checks whether the process exists and whether we are allowed to signal it.

kill -0 $pid && echo "process $pid is running"

The exit status of kill -0 tells us whether the process is alive. After the process is terminated, the check fails with an error message. The wait builtin waits for the background process to finish.

$ sleep 500 & pid=$!
$ kill -0 $pid && echo "process $pid is running"
process 69 is running
$ kill $pid; wait $pid
$ kill -0 $pid
bash: kill: (69) - No such process

Pausing and resuming a process

The SIGSTOP signal suspends a process, and SIGCONT resumes it.

kill -STOP $pid
kill -CONT $pid

In the STAT column of ps, T means stopped and S means sleeping. Like SIGKILL, SIGSTOP cannot be caught. Pressing Ctrl+Z in a terminal sends the related SIGTSTP signal to the foreground job.

$ sleep 600 & pid=$!
$ kill -STOP $pid
$ ps -o pid,stat,cmd -p $pid
    PID STAT CMD
     71 T    sleep 600
$ kill -CONT $pid
$ ps -o pid,stat,cmd -p $pid
    PID STAT CMD
     71 S    sleep 600
$ kill $pid

Killing jobs

The Bash builtin kill accepts job specifications, which are listed by the jobs command.

kill %1

Job %1 is the first background job of the current shell. Using job numbers avoids looking up PIDs for processes started from the same terminal.

$ sleep 700 &
$ sleep 701 &
$ jobs
[1]-  Running                 sleep 700 &
[2]+  Running                 sleep 701 &
$ kill %1
$ jobs
[2]+  Running                 sleep 701 &

Killing processes by name with pkill

The pkill command sends a signal to processes matching a pattern. It accepts the same selection options as pgrep.

pkill -f "sleep 80[12]"
pkill -u jano sleep

By default, the pattern is a regular expression matched against the process name. The -f option matches against the full command line, so we can select only two of the three sleep processes. The -u option limits the matching processes to those of a given user. A signal is specified as with kill, for example pkill -HUP nginx. Run pgrep with the same pattern first to see which processes would be affected.

$ sleep 801 & sleep 802 & sleep 803 &
$ pgrep -a sleep
84 sleep 801
85 sleep 802
86 sleep 803
$ pkill -f "sleep 80[12]"
$ pgrep -a sleep
86 sleep 803
$ pkill -u jano sleep
$ pgrep -a sleep || echo "no sleep processes"
no sleep processes

Best practices for kill

Source

kill(1) manual page

In this article, we have used the kill command to terminate processes, send custom signals, pause and resume processes, and handle signals in scripts, as well as pkill to signal processes by name.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Linux tutorials.