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

Bash:子スクリプトが SIGINT をトラップするときに親スクリプトが SIGINT で終了しないのはなぜですか?

新しい答え:

この質問は、私が当初考えていたよりもはるかに興味深いものです。答えは基本的にここにあります:

子を含む perl スクリプトに送信された場合、SIGINT (^C) はどうなりますか?

これが関連する一口です。 Perl を使用していないことは承知していますが、Bash は C の規則を使用していると思います。

<ブロック引用>

Perl の組み込みシステム関数は、シグナルに関する限り、標準 C ライブラリの C system(3) 関数と同じように機能します。Perl のバージョンの system() またはパイプ オープンまたはバックティックを使用している場合、親 — 1 つの呼び出しシステムbyit と呼ばれるものではなく — 子が実行されている間は SIGINT と SIGQUIT を無視します。

この説明は、可能なさまざまな選択について私が見た中で最高のものです。また、Bash は WCE アプローチを行うとも述べています。つまり、親プロセスが SIGINT を受け取ると、子プロセスが戻るまで待機します。そのプロセス ハンドルが SIGINT から終了した場合、それも SIGINT で終了します。子が他の方法で終了した場合、SIGINT は無視されます。

<ブロック引用>

また、呼び出されたプログラムが SIGINT で終了したかどうか、および SIGINT を無視したかどうか (または他の目的で使用したかどうか) を呼び出しシェルが判断できる方法もあります。 WUE の方法と同様に、シェルは子プロセスが完了するのを待ちます。プログラムが SIGINT で終了したかどうかを判断し、終了した場合はスクリプトを中止します。プログラムが他の終了を行った場合、スクリプトは続行されます。このドキュメントの残りの部分では、物事を行う方法を「WCE」(「待機して協力して終了」の略) と呼びます。

Bash の man ページでこれに関する参照を見つけることができませんが、info docs を引き続き調べます。しかし、私はこれが正しい答えであると 99% 確信しています。

古い回答:

Bash スクリプトのコマンドからのゼロ以外の終了ステータスは、プログラムを終了しません。 echo $? を実行すると ./script2.sh の後 130 と表示されます。set -e を使用してスクリプトを終了できます。 Phsが示唆するように.

$ help set
...
-e  Exit immediately if a command exits with a non-zero status.

@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 "[email protected]"

Linux
  1. 一部のコマンドでBashプロセス置換が機能しないのはなぜですか?

  2. Bash翻訳ファイルにすべてのエラーテキストが含まれていないのはなぜですか?

  3. `source`の後にコマンド名を入力するとオートコンプリートが機能しないのはなぜですか?

  1. bashスクリプトを終了する方法はありますが、ターミナルを終了しない

  2. パターン マッチが bash スクリプトで機能しない

  3. screen を bash で使用すると、$LD_LIBRARY_PATH が設定解除されるのはなぜですか?

  1. 子プロセスのPgidが親のPidではないのはなぜですか?

  2. Sigintが親プロセスに送信されたときに子プロセスに伝播されないのはなぜですか?

  3. 実行後にBashスクリプトが終了しないのはなぜですか?