12

サブプロセスを呼び出して、それとそのすべての子孫に割り込みが送信されるようにする方法はありますか? 実行時間の長い子を呼び出すランチャー スクリプトを強制終了しようとしています。私は試しましたkill -SIGINT $child(これはその子孫に割り込みを送信しないため、ノーオペレーションです)およびkill -SIGINT -$child(インタラクティブに呼び出された場合は機能しますが、スクリプトで実行された場合は機能しません)。

これがテストスクリプトです。長時間実行スクリプトはtest.sh --child. をtest.sh --parent呼び出すと、呼び出されてから、それを強制終了test.sh --child &しようとします。親に子をうまく殺させるにはどうすればよいですか?

#!/bin/bash

if [ "$1" = "--child" ]; then
sleep 1000

elif [ "$1" = "--parent" ]; then
"$0" --child &
for child in $(jobs -p); do
  echo kill -SIGINT "-$child" && kill -SIGINT "-$child"
done
wait $(jobs -p)

else
echo "Must be invoked with --child or --parent."
fi

trap長時間実行されている子をシグナルに変更し、それらをサブプロセスに送信してから待機 できることは知っています( Bash スクリプトから Ctrl+C でバックグラウンド (孫) の子を殺します) が、子スクリプトを変更せずに方法はありますか?

4

4 に答える 4

6
somecommand &

の子の pid を返します$!

somecommand &
pid[0]=$!
anothercommand &
pid[1]=$!
trap "kill ${pid[0]} ${pid[1]}; exit 1" INT
wait

私は、bash ジョブ制御 (bg、fg、jobs) ではなく、このモデルから始めます。通常、init は孤立したプロセスを継承してリープします。どのような問題を解決しようとしていますか?

于 2013-02-04T22:20:52.180 に答える
6

これを読んでください:スクリプトからスクリプトへシグナルSIGINTを送信する方法は?バッシュ

からもinfo bash

   To facilitate the implementation of the user interface to job  control,
   the operating system maintains the notion of a current terminal process
   group ID.  Members of this process group (processes whose process group
   ID is equal to the current terminal process group ID) receive keyboard-
   generated signals such as SIGINT.  These processes are said  to  be  in
   the  foreground.  Background processes are those whose process group ID
   differs from the terminal's; such processes are immune to keyboard-gen‐
   erated signals. 

そのため、プロセス グループ IDbashによってバックグラウンド プロセスとフォアグラウンド プロセスを区別します。プロセス グループ IDがプロセスIDと等しい場合、そのプロセスはフォアグラウンド プロセスであり、シグナルを受信すると終了します。それ以外の場合は終了しません (トラップされない限り)。SIGINT

プロセスグループIDは次のように表示できます

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

&したがって、スクリプト内から( を使用して) バックグラウンド プロセスを実行すると、SIGINTシグナルがトラップされない限り、シグナルは無視されます。

SIGKILLただし、、 などの他のシグナルで子プロセスを強制終了することはできますSIGTERM

たとえば、スクリプトを次のように変更すると、子プロセスが正常に強制終了されます。

#!/bin/bash

if [ "$1" = "--child" ]; then
  sleep 1000
elif [ "$1" = "--parent" ]; then
  "$0" --child &
  for child in $(jobs -p); do
    echo kill "$child" && kill "$child"
  done
  wait $(jobs -p)

  else
  echo "Must be invoked with --child or --parent."
fi

出力:

$ ./test.sh --parent
kill 2187
./test.sh: line 10:  2187 Terminated              "$0" --child
于 2013-02-04T22:36:16.107 に答える