Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bash: Killing all processes in subprocess

In bash I can get the process ID (pid) of the last subprocess through the $! variable. I can then kill this subprocess before it finishes:

(sleep 5) & pid=$!
kill -9 $pid

This works as advertised. If I now extend the subprocess with more commands after the sleep, the sleep command continues after the subprocess is killed, even though the other commands never get executed.

As an example, consider the following, which spins up a subprocess and monitor its assassination using ps:

# Start subprocess and get its pid
(sleep 5; echo done) & pid=$!

# grep for subprocess
echo "grep before kill:"
ps aux | grep "$pid\|sleep 5"

# Kill the subprocess
echo
echo "Killing process $pid"
kill -9 $pid

# grep for subprocess
echo
echo "grep after kill:"
ps aux | grep "$pid\|sleep 5"

# Wait for sleep to finish
sleep 6

# grep for subprocess
echo
echo "grep after sleep is finished:"
ps aux | grep "$pid\|sleep 5"

If I save this to a file named filename and run it, I get this printout:

grep before kill:
username    7464    <...>    bash filename
username    7466    <...>    sleep 5
username    7467    <...>    grep 7464\|sleep 5

Killing process 7464

grep after kill:
username    7466    <...>    sleep 5
username    7469    <...>    grep 7464\|sleep 5

grep after sleep is finished:
username    7472    <...>    grep 7464\|sleep 5

where unimportant information from the ps command is replaced with <...>. It looks like the kill has killed the overall bash execution of filename, while leaving sleep running.

How can I correctly kill the entire subprocess?

like image 200
jmd_dk Avatar asked Jan 06 '17 15:01

jmd_dk


People also ask

How do you kill a process and all its children?

If it is a process group you want to kill, just use the kill(1) command but instead of giving it a process number, give it the negation of the group number. For example to kill every process in group 5112, use kill -TERM -- -5112 .

How do you kill a process tree?

If you select the process at the top of the tree you want kill, then press F9 followed by Enter it will close the process and the entire process tree in one go.


3 Answers

You can set a trap in the subshell to kill any active jobs before exiting:

 (trap 'kill $(jobs -p)' EXIT; sleep 5; echo done ) & pid=$!
like image 75
chepner Avatar answered Oct 21 '22 00:10

chepner


I don't know exactly why that sleep process gets orphaned, anyway instead kill you can use pkill with -P flag to also kill all children

pkill -TERM -P $pid

EDIT: that means that in order to kill a process and all it's children you should use instead

CPIDS=`pgrep -P $pid` # gets pids of child processes
kill -9 $pid
for cpid in $CPIDS ; do kill -9 $cpid ; done
like image 35
MacHala Avatar answered Oct 21 '22 01:10

MacHala


You can have a look at rkill that seems to meet your requirements :

http://www.unix.com/man-page/debian/1/rkill/

rkill [-SIG] pid/name...

When invoked as rkill, this utility does not display information about the processes, but sends them all a signal instead. If not specified on the command line, a terminate (SIGTERM) signal is sent.

like image 30
CCH Avatar answered Oct 21 '22 00:10

CCH