web-dev-qa-db-fra.com

Comment tuer tous les sous-processus de shell?

J'écris un script bash, qui fait plusieurs choses.

Au début, il démarre plusieurs scripts de surveillance, chacun d'eux exécute d'autres outils.

À la fin de mon script principal, je voudrais tuer tout ce qui a été généré par mon Shell.

Ainsi, cela pourrait ressembler à ceci:

#!/bin/bash

some_monitor1.sh &
some_monitor2.sh &
some_monitor3.sh &

do_some_work
...

kill_subprocesses

Le fait est que la plupart de ces moniteurs génèrent leurs propres sous-processus, faisant ainsi (par exemple): killall some_monitor1.sh n'aidera pas toujours.

Une autre façon de gérer cette situation?

37
user80168

Après avoir démarré chaque processus enfant, vous pouvez obtenir son identifiant avec

ID=$!

Ensuite, vous pouvez utiliser les PID stockés pour rechercher et tuer tous les processus de petits-enfants, etc. comme décrit ici ou ici .

27
Péter Török
pkill -P $$

s'adaptera (tue juste ses propres descendants)

EDIT: J'ai eu un downvote, je ne sais pas pourquoi. Quoi qu'il en soit, voici l'aide de -P

   -P, --parent ppid,...
          Only match processes whose parent process ID is listed.

et $$ est le id de processus du script lui-même

87
pihentagy

Si vous utilisez un PID négatif avec kill, il tuera un groupe de processus. Exemple:

kill -- -1234

15
Dennis Williamson
kill $(jobs -p)

Rhys Ulerich suggestion de:

Mettre en garde une condition de concurrence, en utilisant le [code ci-dessous] accomplit ce que Jürgen a suggéré sans provoquer d'erreur quand aucun travail n'existe

[[ -z "$(jobs -p)" ]] || kill $(jobs -p)
9
Jürgen Hötzel

Étendre la réponse de pihentagy pour tuer récursivement tous les descendants (pas seulement les enfants):

kill_descendant_processes() {
    local pid="$1"
    local and_self="${2:-false}"
    if children="$(pgrep -P "$pid")"; then
        for child in $children; do
            kill_descendant_processes "$child" true
        done
    fi
    if [[ "$and_self" == true ]]; then
        kill -9 "$pid"
    fi
}

Maintenant

kill_descendant_processes $$

va tuer les descendants du script/shell actuel.

(Testé sur Mac OS 10.9.5. Ne dépend que de pgrep et kill)

6
Adam Cath

pkill avec optioin "-P" devrait aider:

pkill -P $(pgrep some_monitor1.sh)

à partir de la page de manuel:

   -P ppid,...
          Only match processes whose parent process ID is listed.

Il y a quelques discussions sur linuxquests.org, veuillez vérifier:

http://www.linuxquestions.org/questions/programming-9/use-only-one-kill-to-kill-father-and-child-processes-665753/

3
ybyygu