opscape

Processes and jobs

pkill

Send a signal (TERM by default) to every process whose name or command line matches a pattern.

pkill [-SIGNAL] [OPTION...] PATTERN

12 of 12 examples run in Debian 13.7 on 2026-10-31 · procps 2:4.0.4-9 · manual: pkill(1)

pkill is pgrep that signals instead of printing: the same regular-expression match on the process name (or on the full command line with -f) and the same filters (-u, -P, -n, -x, -F). The default signal is TERM; give another as -HUP, -9 or --signal KILL.

Its strength is also its danger: a pattern is a regular expression matched anywhere in the name, and it hits every matching process you own (all of them, as root). pkill ssh also hits sshd and ssh-agent. The safe habit is to run the same arguments through pgrep -a first, check the list, then press up-arrow and change pgrep -a to pkill.

pkill prints nothing by default; -e reports each process it signaled. Its exit status is 0 if at least one process matched and 1 if none did, which scripts can treat as "was it running?". Compared with killall, pkill matches patterns where killall matches whole names, and its options are the same on every Linux system because both tools come from procps.

Examples

Stop all processes with a given name

sleep 300 & sleep 600 &
pkill sleep
wait
pgrep sleep || echo "no sleep processes left"
output
no sleep processes left

Every process whose name contains sleep gets TERM. pkill is silent; the follow-up pgrep finds nothing and exits 1, so the message prints.

Report what was signaled

sleep 300 & sleep 600 &
pkill -e sleep
output
sleep killed (pid 1797)
sleep killed (pid 1798)

-e (--echo) prints the name and PID of each process signaled. Worth adding whenever pkill runs from a script, so the log shows what it did.

Match the exact process name

sleep 300 &
pkill -x slee; echo "slee: exit $?"
pkill -e -x sleep
output
slee: exit 1
sleep killed (pid 1800)

Without -x, slee would have matched sleep. With it, the whole name must match; no process is named exactly slee, so nothing is signaled and the exit status is 1.

Tell a daemon to reload with HUP

daemon.sh
#!/bin/bash
trap 'echo "HUP received, reloading config"' HUP
while :; do sleep 0.1; done
chmod +x daemon.sh
./daemon.sh &
sleep 0.3
pkill -HUP -x daemon.sh
sleep 0.3
output
HUP received, reloading config

For a script started through its #! line, the process name is the script's file name, so -x daemon.sh matches it. -HUP (or --signal HUP) replaces the default TERM; the script's trap runs and it keeps going. pkill -HUP nginx and pkill -USR1 rsyslogd work the same way.

Kill processes that ignore TERM

bash -c 'trap "" TERM; sleep 300' &
sleep 0.2
pkill -e -x sleep
sleep 0.2
pgrep -a -x sleep
pkill -9 -e -x sleep
output
sleep killed (pid 1814)
1814 sleep 300
sleep killed (pid 1814)

The child shell ignores TERM, and an ignored signal stays ignored in the programs it starts, so sleep survives the first pkill (which still reports it as signaled). -9 sends KILL, which cannot be ignored.

The classic mistake, pkill -f killing its own shell

trap 'echo "outer shell: got TERM as well"' TERM
bash -c 'sleep 300 & pkill -f "sleep 300"; echo "never printed"'
echo "inner shell exit status: $?"
output
Terminated
outer shell: got TERM as well
inner shell exit status: 143

-f matches full command lines, and the inner shell has sleep 300 in its own command line, so pkill terminates it before its echo; the outer shell reports Terminated and status 143. The outer shell matched too; only its trap kept it alive to say so. A script named backup.sh that runs pkill -f backup to stop an earlier run kills itself the same way.

Exclude your own shell with -A

sleep 300 &
pkill -e -A -f 'sleep 300'
echo "still here"
output
sleep killed (pid 1824)
still here

-A (--ignore-ancestors, procps 4) skips the processes in pkill's own ancestry, so only the sleep is signaled. On systems without -A, make the pattern specific enough not to match the calling command, or use a PID file.

Signal only one user's processes

sleep 300 &
pkill -e -u dev sleep
pkill -u root sshd; echo "exit status: $?"
output
sleep killed (pid 1827)
pkill: killing pid 8 failed: Operation not permitted
exit status: 1

-u filters by effective user. The second command matches root's sshd but dev may not signal it: pkill prints the permission error and, having signaled nothing, exits 1. As root, pkill -u alice ends all of a user's processes, which is how to clean up after a stuck login.

Signal only the newest match

sleep 300 & sleep 301 & sleep 302 &
pkill -n -e sleep
pgrep -a sleep
output
sleep killed (pid 1833)
1831 sleep 300
1832 sleep 301

-n picks the most recently started match and -o the oldest. Useful when you just started a second copy by mistake and want to stop only that one.

Signal the process named in a PID file

sleep 300 &
echo $! > app.pid
pkill -e -F app.pid sleep
output
sleep killed (pid 1836)

-F FILE reads the PID from a file, as daemons write them to /run/NAME.pid. Adding a pattern means the PID is signaled only if it still belongs to a sleep, which guards against a stale file whose PID has been reused by something else.

Stop the children of a process

(sleep 300 & sleep 400 & wait) &
sleep 0.2
pkill -e -P $! sleep
output
sleep killed (pid 1840)
sleep killed (pid 1841)

-P PPID selects processes by parent PID; the pattern narrows it to the sleep children (leave the pattern out to match every child). The subshell's two sleep processes are stopped and the subshell's wait returns.

Exit status when nothing matches

pkill nginx
explain
outputexit 1

(no output)

No output and exit status 1. In a script that should not fail when the program is already stopped, write pkill nginx || true.

Common pitfalls

  • pkill -f pattern from a script or bash -c kills the caller when its own command line matches, as shown above. Use -A, a narrower pattern, or -x on the process name.

  • Unanchored patterns: pkill ssh hits sshd (and can cut your own SSH session) and ssh-agent. Check with pgrep -a first and use -x when you mean one exact name.

  • Running pkill -9 as the first move. Processes get no chance to clean up; send the default TERM, give them a few seconds, and only then use -9.

  • As root, a careless pattern matches system processes too. Add -u USER to keep the blast radius to one account.

  • Signal names with the - prefix are fine (pkill -HUP x), but pkill -s HUP x is wrong: -s means session ID. Use --signal HUP for the long form.

GNU vs BSD and macOS

The examples above ran the GNU/Linux version. These are the differences that matter on macOS and the BSDs (written from their documentation, not run here).

  • macOS and FreeBSD pkill share the core options with Linux (-f, -x, -u, -n, -o, -P, -SIGNAL); -A and the --signal long form are procps additions. BSD pkill excludes its own ancestors by default, so the self-kill pitfall mostly bites on Linux.

Options worth knowing

A selection, described in our own words. For the full list, see pkill(1) or pkill --help.

OptionWhat it does
-ePrint the name and PID of each process signaled.
-fMatch the pattern against the full command line, not just the name.
-xRequire the pattern to match the whole name (or command line with -f).
-iMatch case-insensitively.
-cPrint how many processes matched.
-nSignal only the most recently started match.
-oSignal only the least recently started match.
-O SECSMatch only processes running longer than SECS seconds.
-u USERSMatch only processes with these effective users.
-U USERSMatch only processes with these real users.
-P PPIDSMatch only children of these parent PIDs.
-g PGIDSMatch only processes in these process groups.
-s SIDSMatch only processes in these sessions (not a signal option).
-t TTYSMatch only processes on these terminals.
-F FILERead the PIDs to signal from FILE.
-ANever signal pkill's own ancestors, such as the calling shell.
--signal SIGNALSend SIGNAL, by name or number, instead of TERM.
-9Send KILL, which cannot be caught or ignored.
-KILLSend KILL by name.
-TERMSend TERM, the default.
-HUPSend HUP, usually a request to reload configuration.
-INTSend INT, the same as pressing Ctrl-C.
-USR1Send USR1, whose meaning each program defines.
-STOPPause the matching processes.
-CONTResume paused processes.

Related