bash
、ash
、およびdash
を比較すると、bash
のみがSIGTERM
で終了できます。
kill -TERM <pid>
ash
およびbash
の場合、SIGHUP
またはSIGKILL
が必要です
kill -HUP <pid>
kill -KILL <pid>
これの背後にある理由は何ですか?さらに、動作はシステムに依存しているようです。
bash
は、Ubuntu 14.04 Trusty、Ubuntu 16.04 Xenial、Ubuntu 18.04 Bionic、Ubuntu 19.10 Eoan、Ubuntu 20.04 Focal、Debian 8 Jessie、Debian 9 Stretch、Debian 10 Buster、CentOS8ではSIGTERM
で終了します。bash
is not終端はSIGTERM
でCentOS 6、CentOS 7これは私には予想外でしたが、いくつかのビルドを実行すると、bash 4.0ではなくgitからのbashの最新コードで再現可能であることが明らかになりました。そのため、git bisect
は、次のコミットを責任があるものとして特定するのに役立ちました。
% git bisect good
ac50fbac377e32b98d2de396f016ea81e8ee9961 is the first bad commit
commit ac50fbac377e32b98d2de396f016ea81e8ee9961
Author: Chet Ramey <[email protected]>
Date: Wed Feb 26 09:36:43 2014 -0500
Bash-4.3 distribution sources and documentation
Bashの個々のgitコミットはかなり大きく、スコープがそれほど厳密ではない傾向がありますが、そのコミットを数分かけて実行すると、SIGTERMがバイパスすることになっている新しいrl_signal_event_hookなど、readlineがSIGTERMを処理する方法に多くの変更が加えられています。 SIGTERMをチェックし、termsig_handler
を呼び出す場所。
これらの変更の一部は、変更ログの次の新しいエントリと一致します。
Readlineは、入力の読み取り中にシグナルを取得した後、アプリケーションが設定したイベントフック(rl_signal_event_hook)を呼び出し(readは-1/EINTRを返しますが、readlineはシグナルをすぐには処理しません)、アプリケーションが処理できるようにします。現在、SIGHUPまたはSIGTERMでは呼び出されません。
このメッセージから判断すると、行動の変化は意図的なものではないのではないかと思います。
これが意図的であったかどうかの根底に到達することを期待して、このスレッドをバグバッシュメーリングリストに転送します。
これは、bashがreadline
行編集ライブラリを使用している場合、およびbash
がユーザーからの入力を待機している場合にのみ発生します。
_bash --noediting
_はSIGTERM
によって強制終了されません。また、_kill -TERM $$
_を実行している場合、bash
はそれ自体を強制終了しません。
これは、bashがユーザーからの入力を取得するために使用するreadline()
関数が、SIGTERM
用の独自のシグナルハンドラーをインストールし、戻る前に元のシグナル処理を復元するために発生します。 SIGTERM
がユーザーからの入力を待っている間にreadline
が発生した場合、readline()
はNULL
を返します。
readline()
(yy_readline_get()
)を呼び出すbash関数は、NULL
の戻りをEOF
として解釈し、シェルを終了します。このシナリオは、この answer のシナリオと非常に似ています。
これは、SIGTERM
;-)を設定することで、インタラクティブなbashをIGNOREEOF
で存続させることもできることを意味します。
_$ bash
$ IGNOREEOF=10
$ echo $$
11096
<kill -TERM 11096 from another terminal>
$ Use "exit" to leave the Shell.
<kill -TERM 11096 from another terminal>
$ Use "exit" to leave the Shell.
...
<the 10th will get it>
$ exit
$
_