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


10

時々私はすぐにログアウトしたいときはやりますkill -15 -1。bashがSIGTERMを無視していることに気づきました。

はそのようなbashの振る舞いの根拠は何ですか?

正当な理由なしにSIGTERMを無視することは、UNIXではありませんよね。

更新:

すべてに同じ(無)効果:

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

UPDATE2:

man bashから:

bashが対話式の場合、トラップがない場合、SIGTERMは無視されます

故意に行われます。しかし、なぜ?


あなたはどちらの殺害を使用していますか?/bin/killまたはシェル組み込みですか?後者の場合、シェルは独自の組み込みでそれ自体を殺すことはないと思います。
terdon

@terdon:ビルトインを使用しましたが、それが自分で殺さない理由ではないと思います。
のMichałŠrajer

1
すばやくログアウトしたい場合は、Ctrl + dを使用してください
YoMismo

1
@YoMismo: "Xセッションからログアウト"
のMichałŠrajer

2
@MichałŠrajer:Ctrl-Alt-BackspaceはXorgで私のためにこれを行います...しかし、xorg.confでそれを有効にする必要があるかもしれません。
Laszlo Valko、2015

回答:


10

まず、これはbashに固有のものではありません。ATT ksh、dash、zshは同じように動作します。これらはコマンドラインの編集中にSIGTERMとSIGQUITを無視します。mkshについても、終了せずにSIGINTのように扱います。

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

そのためkill 0、対話型シェルを殺すことはありません

kill 0シェルが含まれているプロセスグループ内のすべてのプロセスを強制終了します。簡単に言えば、プロセスグループは、ターミナルのフォアグラウンドで実行されているすべてのプロセス、またはバックグラウンドジョブまたは中断されたジョブのすべてのプロセスで構成されます。

より正確には、これはジョブ制御を備えた最新のシェルで何が起こるかです。このようなシェルで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。それはとにかくあなたの指先で持っていることは非常に危険なコマンドです。

¹ これは、原則としてシェルのマニュアルには記載されていないようです。これは、基礎となるシステムコールの機能です。これはPOSIX仕様で明示的に言及されています。
² 現在、これを行うには、実行jobs -lしてプロセスグループIDを含むジョブのリストを表示し、次にプロセスグループkill -123 -456 …を強制終了します。


5

これはあなたの質問に答えるかもしれません:

Bashがインタラクティブである場合、トラップがない場合、SIGTERMは無視され(「kill 0」はインタラクティブシェルを強制終了しないため)、SIGINTがキャッチされて処理されます(組み込みの待機が割り込み可能になるため)。BashがSIGINTを受信すると、実行中のループから抜け出します。すべての場合において、BashはSIGQUITを無視します。ジョブ制御が有効な場合(ジョブ制御を参照)、BashはSIGTTIN、SIGTTOU、およびSIGTSTPを無視します。

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

デフォルトでは、シェルはSIGHUPを受信すると終了します。終了する前に、対話型シェルは実行中または停止中のすべてのジョブにSIGHUPを再送信します。停止したジョブにはSIGCONTが送信され、SIGHUPを確実に受信します。シェルが特定のジョブにSIGHUPシグナルを送信しないようにするには、disownビルトイン(ジョブ制御ビルトインを参照)を使用してジョブテーブルから削除するか、disown -hを使用してSIGHUPを受信しないようにマークする必要があります。

shoptでhuponexitシェルオプションが設定されている場合(The Shopt Builtinを参照)、インタラクティブログインシェルが終了すると、BashはすべてのジョブにSIGHUPを送信します。

Bashがコマンドの完了を待機していて、トラップが設定されたシグナルを受信した場合、コマンドが完了するまでトラップは実行されません。Bashがwaitビルトインを介して非同期コマンドを待機している場合、トラップが設定されたシグナルを受信すると、128より大きい終了ステータスでwaitビルトインがすぐに戻り、その直後にトラップが実行されます。

出典GNU Bashマニュアル


私はこれを私のupdate2で​​引用しました。男はbashがそうしていると述べているが、なぜそのような決定をしたのかは説明していない。問題は残ります-なぜですか?
のMichałŠrajer
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.