GNU/Linux >> Linux の 問題 >  >> Linux

プロセス グループのすべてのメンバーにシグナルを送信する最良の方法は何ですか?

殺したいツリーが単一のプロセスグループであるかどうかは言いません。 (これは、ツリーがサーバーの起動またはシェル コマンド ラインから分岐した結果である場合によくあります。) 次のように、GNU ps を使用してプロセス グループを検出できます。

 ps x -o  "%p %r %y %x %c "

強制終了したいプロセス グループの場合は、kill(1) を使用します。 コマンドですが、プロセス番号を与える代わりに、否定 を与えてください グループ番号の。たとえば、グループ 5112 のすべてのプロセスを強制終了するには、kill -TERM -- -5112 を使用します。 .


同じプロセス ツリーに属するすべてのプロセスを強制終了します プロセス グループ ID を使用 (PGID )

  • kill -- -$PGID デフォルトのシグナル (TERM を使用) =15)
  • kill -9 -$PGID シグナル KILL を使用 (9)

PGID を取得できます 任意の プロセス ID から (PID ) 同じ プロセス ツリー

  • kill -- -$(ps -o pgid= $PID | grep -o '[0-9]*') (シグナル TERM )
  • kill -9 -$(ps -o pgid= $PID | grep -o '[0-9]*') (シグナル KILL )

説明

  • kill -9 -"$PGID" => シグナル 9 を送信 (KILL ) すべての子と孫へ...
  • PGID=$(ps opgid= "$PID") => Process-Group-ID を取得します 任意の プロセス ID から Process-Parent-ID だけでなく、ツリーの . ps opgid= $PID のバリエーション ps -o pgid --no-headers $PID です ここで pgid pgrp に置き換えることができます .
    しかし:
    • ps PID の場合、先頭にスペースを挿入します 5 桁未満であり、tanager が気づいたように右揃えです。以下を使用できます。
      PGID=$(ps opgid= "$PID" | tr -d ' ')
    • ps from OSX は常にヘッダーを出力するため、Speakus は次のように提案します。
      PGID="$( ps -o pgid "$PID" | grep [0-9] | tr -d ' ' )"
  • grep -o [0-9]* 連続する数字のみを出力します (スペースやアルファベットのヘッダーは出力しません)。

その他のコマンド ライン

PGID=$(ps -o pgid= $PID | grep -o [0-9]*)
kill -TERM -"$PGID"  # kill -15
kill -INT  -"$PGID"  # correspond to [CRTL+C] from keyboard
kill -QUIT -"$PGID"  # correspond to [CRTL+\] from keyboard
kill -CONT -"$PGID"  # restart a stopped process (above signals do not kill it)
sleep 2              # wait terminate process (more time if required)
kill -KILL -"$PGID"  # kill -9 if it does not intercept signals (or buggy)

制限

  • davide と Hubert Kario が気付いたように、kill 同じツリー kill に属するプロセスによって呼び出されます ツリー全体の殺害を終了する前に自分自身を殺すリスク
  • したがって、別の Process-Group-ID を持つプロセスを使用してコマンドを実行してください。 .

長編

> cat run-many-processes.sh
#!/bin/sh
echo "ProcessID=$$ begins ($0)"
./child.sh background &
./child.sh foreground
echo "ProcessID=$$ ends ($0)"

> cat child.sh
#!/bin/sh
echo "ProcessID=$$ begins ($0)"
./grandchild.sh background &
./grandchild.sh foreground
echo "ProcessID=$$ ends ($0)"

> cat grandchild.sh
#!/bin/sh
echo "ProcessID=$$ begins ($0)"
sleep 9999
echo "ProcessID=$$ ends ($0)"

「&」を使用してバックグラウンドでプロセス ツリーを実行します

> ./run-many-processes.sh &    
ProcessID=28957 begins (./run-many-processes.sh)
ProcessID=28959 begins (./child.sh)
ProcessID=28958 begins (./child.sh)
ProcessID=28960 begins (./grandchild.sh)
ProcessID=28961 begins (./grandchild.sh)
ProcessID=28962 begins (./grandchild.sh)
ProcessID=28963 begins (./grandchild.sh)

> PID=$!                    # get the Parent Process ID
> PGID=$(ps opgid= "$PID")  # get the Process Group ID

> ps fj
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
28348 28349 28349 28349 pts/3    28969 Ss   33021   0:00 -bash
28349 28957 28957 28349 pts/3    28969 S    33021   0:00  \_ /bin/sh ./run-many-processes.sh
28957 28958 28957 28349 pts/3    28969 S    33021   0:00  |   \_ /bin/sh ./child.sh background
28958 28961 28957 28349 pts/3    28969 S    33021   0:00  |   |   \_ /bin/sh ./grandchild.sh background
28961 28965 28957 28349 pts/3    28969 S    33021   0:00  |   |   |   \_ sleep 9999
28958 28963 28957 28349 pts/3    28969 S    33021   0:00  |   |   \_ /bin/sh ./grandchild.sh foreground
28963 28967 28957 28349 pts/3    28969 S    33021   0:00  |   |       \_ sleep 9999
28957 28959 28957 28349 pts/3    28969 S    33021   0:00  |   \_ /bin/sh ./child.sh foreground
28959 28960 28957 28349 pts/3    28969 S    33021   0:00  |       \_ /bin/sh ./grandchild.sh background
28960 28964 28957 28349 pts/3    28969 S    33021   0:00  |       |   \_ sleep 9999
28959 28962 28957 28349 pts/3    28969 S    33021   0:00  |       \_ /bin/sh ./grandchild.sh foreground
28962 28966 28957 28349 pts/3    28969 S    33021   0:00  |           \_ sleep 9999
28349 28969 28969 28349 pts/3    28969 R+   33021   0:00  \_ ps fj

コマンド pkill -P $PID 孫を殺さない:

> pkill -P "$PID"
./run-many-processes.sh: line 4: 28958 Terminated              ./child.sh background
./run-many-processes.sh: line 4: 28959 Terminated              ./child.sh foreground
ProcessID=28957 ends (./run-many-processes.sh)
[1]+  Done                    ./run-many-processes.sh

> ps fj
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
28348 28349 28349 28349 pts/3    28987 Ss   33021   0:00 -bash
28349 28987 28987 28349 pts/3    28987 R+   33021   0:00  \_ ps fj
    1 28963 28957 28349 pts/3    28987 S    33021   0:00 /bin/sh ./grandchild.sh foreground
28963 28967 28957 28349 pts/3    28987 S    33021   0:00  \_ sleep 9999
    1 28962 28957 28349 pts/3    28987 S    33021   0:00 /bin/sh ./grandchild.sh foreground
28962 28966 28957 28349 pts/3    28987 S    33021   0:00  \_ sleep 9999
    1 28961 28957 28349 pts/3    28987 S    33021   0:00 /bin/sh ./grandchild.sh background
28961 28965 28957 28349 pts/3    28987 S    33021   0:00  \_ sleep 9999
    1 28960 28957 28349 pts/3    28987 S    33021   0:00 /bin/sh ./grandchild.sh background
28960 28964 28957 28349 pts/3    28987 S    33021   0:00  \_ sleep 9999

コマンド kill -- -$PGID 孫を含むすべてのプロセスを強制終了します。

> kill --    -"$PGID"  # default signal is TERM (kill -15)
> kill -CONT -"$PGID"  # awake stopped processes
> kill -KILL -"$PGID"  # kill -9 to be sure

> ps fj
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
28348 28349 28349 28349 pts/3    29039 Ss   33021   0:00 -bash
28349 29039 29039 28349 pts/3    29039 R+   33021   0:00  \_ ps fj

結論

この例 PID で気づきました と PGID 等しい (28957 )。
これが、最初に kill -- -$PID と思った理由です。 で十分でした。ただし、プロセスが Makefile 内で生成される場合 プロセス ID グループ ID とは異なります .

kill -- -$(ps -o pgid= $PID | grep -o [0-9]*)だと思います 別の グループ ID から呼び出されたときにプロセス ツリー全体を強制終了するための最もシンプルなトリックです。 (別のプロセスツリー)


pkill -TERM -P 27888

これにより、親プロセス ID 27888 を持つすべてのプロセスが強制終了されます。

またはより堅牢:

CPIDS=$(pgrep -P 27888); (sleep 33 && kill -KILL $CPIDS &); kill -TERM $CPIDS

これは 33 秒後に強制終了をスケジュールし、丁寧にプロセスの終了を要求します。

すべての子孫を終了するには、この回答を参照してください。


Linux
  1. すべてのディスク IO を使用しているプロセス

  2. Javaでメモリ不足の状態を処理する最良の方法は何ですか?

  3. /bin を削除しました。回復する最良の方法は何ですか?

  1. システムはいつ SIGTERM をプロセスに送信しますか?

  2. 分割後にファイルを再度結合する最良の方法は何ですか?

  3. SELinuxを学ぶ最良の方法は何ですか?

  1. ディレクトリ内のすべてのファイルとサブフォルダーを削除する最速の方法は何ですか?

  2. .bashrc で環境変数を設定する最良の方法は何ですか?

  3. /var/www で Apache 2 のユーザー www-data のアクセス許可を処理する最良の方法は何ですか?