bashがSIGTERMを無視するのはなぜですか?

bashがSIGTERMを無視するのはなぜですか?

すぐにログアウトしたいときは、このようにしますkill -15 -1。 bashがSIGTERMを無視することがわかりました。

知りたいこのbash動作の理由は何ですか

正当な理由なしにSIGTERMを無視することはUNIXと非常に似ていませんか?

修正する:

すべての人に同じ(なし)効果があります。

$ kill -TERM $$
$ type kill
kill is a shell builtin
$ command kill -TERM $$
$ /bin/kill -TERM $$

アップデート2:

~から男乱交:

Bashがインタラクティブの場合、トラップなしでSIGTERMを無視します。

だからこれは意図的なものです。しかし、なぜ?

答え1

まず第一に、これはbashに限定されません。 ATT ksh、dash、zsh は同じ方法で動作します。コマンドライン編集中にSIGTERMとSIGQUITを無視します。 mkshの場合は終了しませんが、SIGINTとして扱われます。

ksh マニュアルと bash マニュアルはどちらも、次の用語で SIGTERM を無視することを正当化します。

これにより、kill 0対話型シェルは終了しません。

kill 0すべてのプロセスを終了プロセスグループシェルは1にあります。簡単に言うと、プロセスグループは、端末のフォアグラウンドで実行されているか、バックグラウンドでジョブがあるか、保留中のすべてのプロセスで構成されます。

より正確には、これが現代のシェルで起こるものです。職業管理。このようなシェルでは、kill 0シェルは独自のプロセスグループに属するため、役に立たない。古い貝(またはそれ以降の現代貝)set +m)バックグラウンドコマンドの場合、プロセスグループは作成されません。したがって、このコマンドを使用すると、kill 0ログアウトせずにすべてのバックグラウンドコマンドを終了できます。 ² したがって、kill 0根拠は古く、もはや有効ではありませんが、以前のバージョンとの互換性は維持されます。

しかし、他の同様の状況では、シェルを免疫にすることが役に立つかもしれません。端末を占有しているプロセスがあり、ログアウトせずにそのプロセスを終了する状況を考えてみましょう。多くのシステムには同様のツールがあります。pkill端末で実行されているプロセスを終了できます。信号を無視するシェルを除いて、現在端末で実行されているすべてのプロセスを実行または終了pkill -t $TTYできます。pkill -QUIT -t $TTY

シェルは通常、ユーザーが終了した場合(exitまたは同じコマンドを使用logout)、端末が入力終了信号を送信すると(ユーザーがCtrl+を押してこれを発生させることができるD)、消えたり完全に消えたりします。最後に、シェルはSIGHUP信号を受信し、信号を無視しません。

Xセッションからログアウトするユースケースの場合、kill -15 -1これはシェルがSIGHUPを受信できるようにしたターミナルエミュレータを終了するためです。実際にXサーバーをシャットダウンするだけで十分ですが、そのためにはそのプロセスIDを見つける必要があります。テキストセッションで同じコマンドを使用するには、次のようにしますkill -15 -1; exit。とにかくかなり危険な命令です。

1一般的なシェルマニュアルにはこれに言及していないようです。これは基本的なシステムコールの機能です。で明示的に言及POSIX仕様
²今日これを行うには、jobs -lタスクリストの表示とそのプロセスグループIDを実行してからkill -123 -456 …プロセスグループを終了します。

答え2

これはあなたの質問に答えることができます:

Bashがインタラクティブの場合、トラップなしでSIGTERMを無視し(したがって、「kill 0」がインタラクティブシェルを終了しない)、SIGINTがキャプチャされて処理されます(スタンバイの組み込みが中断されるように)。 BashがSIGINTを受け取ると、すべての実行ループを中断します。すべての場合において、BashはSIGQUITを無視します。ジョブ制御が適用される場合(ジョブ制御を参照)、BashはSIGTTIN、SIGTTOU、およびSIGTSTPを無視します。

Bashによって実行される非組み込みコマンドは、シグナルハンドラをシェルが親から継承した値に設定します。ジョブ制御が無効になると、非同期コマンドはこれらの継承されたハンドラーに加えてSIGINTとSIGQUITを無視します。コマンド置換の結果として実行されるコマンドは、キーボードから生成されたジョブ制御信号SIGTTIN、SIGTTOU、およびSIGTSTPを無視します。

デフォルトでは、シェルはSIGHUPを受信した後に終了します。対話型シェルは、シャットダウン前に実行中または停止したすべてのジョブにSIGHUPを再送信します。停止したジョブは、SIGHUPを受信できるようにSIGCONTに送信されます。シェルが特定のジョブにSIGHUP信号を送信しないようにするには、disown組み込み関数を使用してジョブテーブルからその信号を削除するか(タスク制御組み込み関数を参照)、disown -hを使用して受信しないようにマークします。ため息。

huponexitシェルオプションがshoptを使用して設定されている場合(Shoptの組み込みを参照)、Bashは対話型ログインシェルの終了時にすべてのジョブにSIGHUPを送信します。

Bashがコマンドが完了するのを待ってトラップが確立されたことを知らせると、コマンドが完了するまでトラップは実行されません。 Bashがwait組み込み関数を介して非同期コマンドを待機しているときにトラップセットを持つ信号を受信すると、wait組み込み関数は128より大きい終了状態に即座に返され、すぐにトラップが実行されます。

源泉:GNU バッシュマニュアル

関連情報