I want to kill a whole process tree. What is the best way to do this using any common scripting languages? I am looking for a simple solution.
相关问题
- How to get the return code of a shell script in lu
- Is shmid returned by shmget() unique across proces
- how to get running process information in java?
- Stop child process when parent process stops
- Invoking Mirth Connect CLI with Powershell script
Thanks for your wisdom, folks. My script was leaving some child processes on exit and the negation tip made things easier. I wrote this function to be used in other scripts if necessary:
Cheers.
Here is a variation of @zhigang's answer which does without AWK, relying only on Bash's native parsing possibilities:
It seems to work fine on both Macs and Linux. In situations where you can't rely on being able to manage process groups -- like when writing scripts for testing a piece of software which must be built in multiple environments -- this tree-walking technique is definitely helpful.
Kill all the processes belonging to the same process tree using the Process Group ID (
PGID
)kill -- -$PGID
Use default signal (TERM
= 15)kill -9 -$PGID
Use the signalKILL
(9)You can retrieve the
PGID
from any Process-ID (PID
) of the same process treekill -- -$(ps -o pgid= $PID | grep -o '[0-9]*')
(signalTERM
)kill -9 -$(ps -o pgid= $PID | grep -o '[0-9]*')
(signalKILL
)Special thanks to tanager and Speakus for contributions on
$PID
remaining spaces and OSX compatibility.Explanation
kill -9 -"$PGID"
=> Send signal 9 (KILL
) to all child and grandchild...PGID=$(ps opgid= "$PID")
=> Retrieve the Process-Group-ID from any Process-ID of the tree, not only the Process-Parent-ID. A variation ofps opgid= $PID
isps -o pgid --no-headers $PID
wherepgid
can be replaced bypgrp
.But:
ps
inserts leading spaces whenPID
is less than five digits and right aligned as noticed by tanager. You can use:PGID=$(ps opgid= "$PID" | tr -d ' ')
ps
from OSX always print the header, therefore Speakus proposes:PGID="$( ps -o pgid "$PID" | grep [0-9] | tr -d ' ' )"
grep -o [0-9]*
prints successive digits only (does not print spaces or alphabetical headers).Further command lines
Limitation
kill
is invoked by a process belonging to the same tree,kill
risks to kill itself before terminating the whole tree killing.Long story
Run the process tree in background using '&'
The command
pkill -P $PID
does not kill the grandchild:The command
kill -- -$PGID
kills all processes including the grandchild.Conclusion
I notice in this example
PID
andPGID
are equal (28957
).This is why I originally thought
kill -- -$PID
was enough. But in the case the process is spawn within aMakefile
the Process ID is different from the Group ID.I think
kill -- -$(ps -o pgid= $PID | grep -o [0-9]*)
is the best simple trick to kill a whole process tree when called from a different Group ID (another process tree).If you want to kill a process by name:
or
if you know pass the pid of the parent process, here's a shell script that should work:
I use a little bit modified version of a method described here: https://stackoverflow.com/a/5311362/563175
So it looks like that:
where 24901 is parent's PID.
It looks pretty ugly but does it's job perfectly.