Ich möchte einen ganzen Prozessbaum töten. Wie kann ich das am besten mit einer der gängigen Skriptsprachen erreichen? Ich bin auf der Suche nach einer einfachen Lösung.
Antworten
Zu viele Anzeigen?Hier ist eine Variante der Antwort von @zhigang, die ohne AWK auskommt und sich nur auf die nativen Parsing-Möglichkeiten der Bash verlässt:
function killtree {
kill -STOP "$1"
ps -e -o pid= -o ppid= | while read -r pid ppid
do
[[ $ppid = $1 ]] || continue
killtree "$pid" || true # Skip over failures
done
kill -CONT "$1"
kill -TERM "$1"
}
Es scheint sowohl auf Macs als auch auf Linux gut zu funktionieren. In Situationen, in denen man sich nicht auf die Verwaltung von Prozessgruppen verlassen kann - etwa beim Schreiben von Skripten für das Testen einer Software, die in mehreren Umgebungen erstellt werden muss - ist diese Technik des Tree-Walking definitiv hilfreich.
Dies ist meine Version des Tötens aller Kindprozesse mit Bash-Skript. Sie verwendet keine Rekursion und hängt vom Befehl pgrep ab.
Utilice
killtree.sh PID SIGNAL
Inhalt von killtrees.sh
#!/bin/bash
PID=$1
if [ -z $PID ];
then
echo "No pid specified"
fi
PPLIST=$PID
CHILD_LIST=`pgrep -P $PPLIST -d,`
while [ ! -z "$CHILD_LIST" ]
do
PPLIST="$PPLIST,$CHILD_LIST"
CHILD_LIST=`pgrep -P $CHILD_LIST -d,`
done
SIGNAL=$2
if [ -z $SIGNAL ]
then
SIGNAL="TERM"
fi
#do substring from comma to space
kill -$SIGNAL ${PPLIST//,/ }
Um die gesamte Prozessgruppe auf einmal zu beenden, genau wie ^C
tut:
PID="$(pgrep -f unique_command_line_part)"
if [[ -n "$PID" ]]
then
PGID="$(ps --no-headers -p $PID -o pgid)"
kill -SIGINT -- -${PGID// /}
fi
Jede Zeile wird erklärt in diese Antwort
Es ist wahrscheinlich besser, den Elternteil vor den Kindern zu töten, da der Elternteil sonst wahrscheinlich wieder neue Kinder zeugt, bevor er selbst getötet wird. Diese werden die Tötung überleben.
Meine Version von ps unterscheidet sich von der obigen; vielleicht ist sie zu alt, daher das seltsame Grepping...
Die Verwendung eines Shell-Skripts anstelle einer Shell-Funktion hat viele Vorteile...
Im Grunde genommen ist es jedoch Zhigangs Idee
#!/bin/bash
if test $# -lt 1 ; then
echo >&2 "usage: kiltree pid (sig)"
fi ;
_pid=$1
_sig=${2:-TERM}
_children=$(ps j | grep "^[ ]*${_pid} " | cut -c 7-11) ;
echo >&2 kill -${_sig} ${_pid}
kill -${_sig} ${_pid}
for _child in ${_children}; do
killtree ${_child} ${_sig}
done