Bash – Kill the parent of a child pipe process

bashkillpipeprocess

I have a small script to demonstrate what I want to do

#!/bin/bash
> z
tail -f z | grep 'd' &
echo $!

The $! gives the PID of the grep process. I want to be able to kill the tail process at the same time as killing the grep process. Doing kill "pid of grep"does not kill the tail process. Nor does killall grep. I could use killall tail but I think this would be dangerous.

Best Answer

Enclose your command with parentheses:

( tail -f z | grep 'd' ) &
kill -- -$!

This will kill the whole sub-process.

Here, by specifying a negative PID to kill, we kill the whole process group. See man 1 kill:

Negative PID values may be used to choose whole process groups; see the PGID column in ps command output.

Or man 2 kill:

If pid is less than -1, then sig is sent to every process in the process group whose ID is -pid.

However, kill -PID will only work if job control is enabled in bash (the default for interactive shells). Else, your subprocess won't have a dedicated process group and the kill command will fail with kill: (-PID) - No such process

To work around that, either activate job control in bash (set -m), or use pkill -P $!

Related Question