Linuxシステムでは、bash組み込みコマンドdisown
を使用して、現在のセッションからジョブを削除できます。 bashはこの機能をどのように実装しますか?ここではsetsid()
が使用されていますか?使用されている場合、bashはどのようにして子プロセスをトリガーしてsetsid()
を呼び出しますか?信号を使用していますか?
いいえ。disown
はnot現在のセッションからジョブを削除し[1]、端末からジョブを切り離さず、セッション時にカーネルがジョブを送信する信号に影響を与えません。リーダーが終了するか、制御端末が取り壊されたとき。
disown
は、bash自身のジョブテーブルでのみ機能し、bashが制御しているジョブの概念のみを変更し、bash自体の動作、つまり、bashが受信したSIGHUP
を再送信するジョブにのみ影響します。処理する。そのSIGHUP
再送信は、bash
[2]の追加機能であり、標準では必要なく、OSによって提供されるジョブ制御とは関係ありません。
簡単な例でそれを見ることができます。ここでは、script(1)
を使用して、ptyとその中で実行されるインタラクティブなシェルセッションを作成しています。
$ script /dev/null -qc bash
$ sh -c 'sleep 555 & sleep .1; kill -STOP $!; trap "echo hupped!" HUP; sleep 666' &
[1] 3837
$ disown -a
$ jobs
# no jobs known to bash
$ pgrep -as0
# show all processes from the current session
3836 bash
3837 sh -c sleep 555 & sleep .1; kill -STOP $!; trap "echo hupped!" HUP; sleep 666
3838 sleep 555
3841 sleep 666
$ kill -HUP $$
# seppuku the session leader
Hangup
hupped!
ここで、カーネルはSIGHUP
シグナルをバックグラウンドプロセスグループ(=ジョブ)に送信します。これは、そのプロセスの1つが停止しているためです。また、カーネルの所有権を剥奪してもnotそれが起こらないようにします。
sh -c '...'
のすべてのプロセスは、「バックグラウンド」sleep &
を含め、同じジョブの一部です。シェルスクリプトは、デフォルトではジョブ制御を行いません。
バックグラウンドプロセスグループのメンバーが停止していない場合、SIGHUP
は送信されません。
$ script /dev/null -qc bash
$ sh -c 'sleep 555 & trap "echo hupped!" HUP; sleep 666' &
[1] 3270
$ disown -a
$ kill -HUP $$
# sleep 555, 666 and sh -c are still running
最後に、bashがセッションリーダーであるかどうか、またはジョブが実行中、停止中かどうかに関係なく、bashはテーブルからすべてのジョブ(それ自体で開始され、所有権を剥奪されていないジョブのみ)にSIGHUP
を送信します。等:
$ bash
$ sh -c 'sleep 555 & trap "echo hupped!" HUP; sleep 666' &
[1] 3413
$ kill -HUP $$
Hangup
hupped!
Hangup
[1]とにかく行うことは不可能です。 setsid()
は、notプロセスグループリーダーであるプロセスのみを新しいセッションにすることができます。移動する方法はありません。新規または既存のセッションへのジョブ全体。
[2]これはbashのマンページに記載されています:
シェルは、
SIGHUP
を受信するとデフォルトで終了します。終了する前に、対話型シェルは実行中または停止中のすべてのジョブにSIGHUP
を再送信します。停止したジョブはSIGCONT
に送信され、SIGHUP
を確実に受信します。シェルが特定のジョブにシグナルを送信しないようにするには、disown
が組み込まれているジョブテーブルから削除するか(以下のシェルビルドコマンドを参照)、disown -h
を使用してSIGHUP
を受信しないようにマークする必要があります。 。
loginbashシェルが終了時にジョブにHUP
を送信する原因となるshopt -s huponexit
もあります(シグナルのためかどうかは関係ありません)。 )、これもOSの標準のジョブ制御機能と紛らわしい方法で重複しています。