Как убить все подпроцессы оболочки? - PullRequest
35 голосов
/ 11 апреля 2010

Я пишу bash-скрипт, который делает несколько вещей.

Сначала запускается несколько сценариев монитора, каждый из которых запускает некоторые другие инструменты.

В конце моего основного сценария я хотел бы убить все вещи, которые были созданы из моей оболочки.

Итак, это может выглядеть так:

#!/bin/bash

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

do_some_work
...

kill_subprocesses

Дело в том, что большинство этих мониторов порождают свои собственные подпроцессы, поэтому (например): killall some_monitor1.sh не всегда поможет.

Есть ли другой способ справиться с этой ситуацией?

Ответы [ 6 ]

87 голосов
/ 12 июля 2013
pkill -P $$

подойдет (просто убивает своих потомков)

РЕДАКТИРОВАТЬ: У меня есть пониженное голосование, не знаю почему. В любом случае вот помощь -P

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

и $$ - это идентификатор процесса самого скрипта

25 голосов
/ 11 апреля 2010

После запуска каждого дочернего процесса вы можете получить его идентификатор с помощью

ID=$!

Затем вы можете использовать сохраненные PID для поиска и уничтожения всех процессов внука и т. Д., Как описано здесь или здесь .

12 голосов
/ 12 апреля 2010

Если вы используете отрицательный PID с kill, это уничтожит группу процессов. Пример:

kill -- -1234

9 голосов
/ 12 апреля 2010
kill $(jobs -p)

Предложение Риса Улериха :

Оставить условие гонки, используя [код ниже], выполняет то, что предложил Юрген, не вызывая ошибки при отсутствии заданий

[[ -z "$(jobs -p)" ]] || kill $(jobs -p)
6 голосов
/ 17 ноября 2014

Расширение ответа Пиентайи, чтобы рекурсивно убить всех потомков (не только детей):

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
}

Теперь

kill_descendant_processes $$

уничтожит потомков текущего скрипта / оболочки.

(протестировано на Mac OS 10.9.5. Зависит только от pgrep и kill)

3 голосов
/ 12 апреля 2010

pkill с опцией "-P" должно помочь:

pkill -P $(pgrep some_monitor1.sh)

со страницы руководства:

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

На linuxquests.org есть обсуждения, пожалуйста, проверьте:

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

...