web-dev-qa-db-ja.com

シェルのすべてのサブプロセスを強制終了する方法は?

私はいくつかのことを行うbashスクリプトを書いています。

最初にいくつかの監視スクリプトを起動し、それぞれが他のツールを実行します。

メインスクリプトの最後で、シェルから生成されたすべてのものを削除したいと思います。

したがって、次のようになります。

#!/bin/bash

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

do_some_work
...

kill_subprocesses

問題は、これらのモニターの大部分が独自のサブプロセスを生成するため、(たとえば)killall some_monitor1.shは常に役立つとは限りません。

この状況を処理する他の方法はありますか?

37
user80168

各子プロセスを開始した後、そのIDを取得できます

ID=$!

次に、保存されたPIDを使用して、 here または here で説明されているように、すべての孫などのプロセスを見つけて強制終了します。

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

収まります(自分の子孫を殺すだけです)

編集:私は下票を得た、理由はわからない。とにかくここに-Pの助けがあります

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

および$$スクリプト自体のプロセスID です

87
pihentagy

killで負のPIDを使用すると、プロセスグループが強制終了されます。例:

kill -- -1234

15
kill $(jobs -p)

Rhys Ulerich の提案:

[以下のコード]を使用して競合状態を警告すると、ジョブが存在しないときにエラーを発生させることなくユルゲンが提案したことを達成できます。

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

子孫だけでなくすべての子孫を再帰的に殺すために、pihentagyの答えを拡張します。

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のみに依存)

6
Adam Cath

optioin "-P"を使用したpkillは、次のことに役立ちます。

pkill -P $(pgrep some_monitor1.sh)

manページから:

   -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/

3
ybyygu