| Tested on | Red Hat Enterprise Linux 10.2 (Coughlan) |
|---|---|
| Package | procps-ng 4.0.4-11.el10 (pkill, ps, pgrep) |
| Applies to | Any Linux distribution with procps-ng or procps (pkill --parent / -P) |
| Privilege | Normal user for your own processes; sudo or root to signal other users' processes |
| Scope | Signal direct child processes with pkill -P PARENT_PID ., list them with ps --ppid, and optionally clean up simple Bash background workers with an EXIT trap. Does not cover grandchildren or recursive process-tree kills. |
| Related guides | kill and pkill cheat sheet ps command cheat sheet Linux process management Bash trap Ctrl+C Check if a script is already running |
Killing the parent does not necessarily stop its children. pkill -P
lets you target the parent's direct child processes instead.
Quick answer
To send SIGTERM to every direct child of a parent process:
pkill -P PARENT_PID .Here:
pkillsends a signal to matching processes.-P PARENT_PIDlimits the match to processes whose direct parent isPARENT_PID..is the required name pattern and matches any process name.- Because no signal is specified,
pkillsends SIGTERM.
| Goal | Command |
|---|---|
| List direct children | ps -o pid,ppid,cmd --ppid PARENT_PID |
| Signal all direct children | pkill -P PARENT_PID . |
| Show processes being signaled | pkill -e -P PARENT_PID . |
| Signal current shell/script children | pkill -P $$ . |
| Force-kill direct children | pkill -KILL -P PARENT_PID . |
Find child processes of a parent PID
Every process row includes a parent PID (PPID). Direct children of the
same parent share that value.
Start a parent shell with three background sleep workers so you have a
concrete example to inspect:
bash -c 'sleep 300 & sleep 300 & sleep 300; wait' &
PARENT=$!
sleep 1List direct children of that parent:
ps -o pid,ppid,cmd --ppid "$PARENT" --no-headersSample output:
10145 10143 sleep 300
10146 10143 sleep 300
10147 10143 sleep 300Each PPID column value should match $PARENT. For more ps filters,
see the ps command cheat sheet.
Kill direct child processes with pkill -P
Signal every direct child of the parent from the example above:
pkill -e -P "$PARENT" .-P "$PARENT" restricts the match to processes whose parent PID is
$PARENT. . is the required name pattern and matches any process name
among those children. With no signal name on the command line, pkill
sends SIGTERM.
-e (--echo) prints the process name and PID of each match. It still
sends the signal; it is not a preview or dry run.
Sample output:
sleep killed (pid 10145)
sleep killed (pid 10146)
sleep killed (pid 10147)Check whether the parent still has direct children:
ps -o pid --ppid "$PARENT" --no-headersIf the command prints no rows, the parent currently has no direct child processes left.
When SIGTERM is not enough, force-kill the same direct-child set:
pkill -KILL -P "$PARENT" .-KILL is the signal name beginners can read directly; -9 is the
numeric equivalent. Use force-kill only after a normal SIGTERM stop fails.
For other signals and name-based pkill, see the
kill and pkill cheat sheet.
Use pkill -P with the current shell PID
Inside a Bash script, $$ is the PID of the current shell or script.
Combine it with -P and . to signal every direct child of that script:
#!/bin/bash
cleanup() {
pkill -P "$$" .
}
trap cleanup EXIT
long_running_task &
helper_task &
waitWhen the script exits, the EXIT trap runs pkill -P "$$" .:
$$— PID of the current shell or script-P "$$"— restrict matches to its direct children.— match any process name- no signal specified — SIGTERM by default
That works when those children still list the script as their parent at cleanup time. For Ctrl+C and more complex signal handling, see Bash trap Ctrl+C.
Common problems
| Symptom | Likely cause | Fix |
|---|---|---|
pkill -P matches nothing |
Wrong parent PID, children already exited, or pattern too narrow | Run ps -p PARENT_PID and ps --ppid PARENT_PID; use . to match any child name |
| Some processes keep running | They are grandchildren, not direct children | -P matches only direct children; it does not recursively walk the process tree. See Linux process management for broader stop methods |
pkill -P $$ . does nothing |
No background children of that shell | Start jobs with command & first; $$ is the shell PID, not job ID %1 |
| Process ignores SIGTERM | Handler catches or masks the signal | Retry with pkill -KILL -P PARENT_PID . after a short wait |
| Permission denied | Child owned by another user | Run with sudo or as that user |
References
Summary
Use pkill -P PARENT_PID . when you need to signal every direct child of
one parent without matching unrelated processes elsewhere. pkill always
needs a name pattern; -P adds the parent filter; . selects all names
among those children; the default signal is SIGTERM.
List direct children first with ps --ppid when you want to confirm what
will be affected. In a simple Bash script, pkill -P "$$" . on an
EXIT trap is a convenient way to stop direct child workers before the
interpreter exits. Remember that -P does not reach grandchildren — only
the immediate children of the PID you pass.

