15

script1.sh:

 #!/bin/bash    

./script2.sh
 echo after-script

script2.sh:

#!/bin/bash

function handler {
  exit 130
}

trap handler SIGINT

while true; do true; done

端末から script1.sh を起動し、Ctrl+Cを使用して SIGINT をそのプロセス グループに送信すると、シグナルが script2.sh によってトラップされ、script2.sh が終了すると、script1.sh が「after-script」を出力します。ただし、script2.sh を呼び出す行の直後に script1.sh が終了すると予想していました。この例では、なぜこれが当てはまらないのでしょうか?

追加の備考 (編集):

  • script1.sh と script2.sh は同じプロセス グループにあるため、コマンド ラインで+を押すと、両方のスクリプトにSIGINT が送信されます。そのため、script2.sh が終了したときに script1.sh が続行するとは思わないのです。CtrlC

  • script2.sh の「トラップ ハンドラ SIGINT」行をコメント アウトすると、script2.sh が存在した直後に script1.sh が終了します。script2.sh は同じ終了コード (130) を生成するため、なぜ動作が異なるのかを知りたいです。

4

5 に答える 5

2

@seanmcl の更新された回答の 2 番目の部分は正しく、http://www.cons.org/cracauer/sigint.htmlへのリンクは、注意深く読むのに非常に適したものです。

そのリンクから、「システムの数値を調べたとしても、特別な数値を使用して exit(3) によって適切な終了ステータスを「偽造」することはできません」。実際、それは @Hermann Speiche の script2.sh で試みられていることです。

1 つの答えは、次のように script2.sh の関数ハンドラーを変更することです。

function handler {
  # ... do stuff ...
  trap INT
  kill -2 $$
}

これにより、シグナルハンドラーが効果的に削除され、SIGINT が「再スロー」され、bash プロセスが適切なフラグで終了し、親の bash プロセスが最初に送信された SIGINT を正しく処理できるようになります。このように、set -eまたはその他のハックを使用する必要はありません。

また、SIGINT を送信したときに正しく動作しない実行可能ファイルがある場合 (上記のリンクの「適切なプログラムになる方法」に準拠していない、たとえば、通常の戻りコードで終了する)、1 つの方法があることにも注意してください。これを回避するには、次のようなスクリプトでそのプロセスへの呼び出しをラップします。

#!/bin/bash

function handler {
  trap INT
  kill -2 $$
}

trap handler INT
badprocess "$@"
于 2014-09-17T14:42:38.720 に答える