Linuxシステムでは、bash組み込みコマンドをdisown
使用して現在のセッションからジョブを削除できます。 Bashはこの機能をどのように実装しますか?ここで使用されますsetsid()
。使用されている場合、bashは子プロセス呼び出しをどのようにトリガーしますかsetsid()
?信号を使用しますか?
答え1
disown
いいえいいえ現在のセッション[1]からジョブを削除しても、ジョブは端末から切り離されず、セッションリーダーが終了したとき、または制御端末が解体されたときにカーネルが送信する信号には影響しません。
disown
SIGHUP
bashの独自のタスクリストにのみ適用され、bashが制御する操作に対するbashの考えだけを変更し、bashの独自の動作にのみ影響します。つまり、bashプロセスで受信したジョブを再送信します。再送信は、標準で要求されないSIGHUP
[2]の追加機能であり、オペレーティングシステムによって提供されるタスク制御とは無関係です。bash
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つを停止して放棄するので、バックグラウンドプロセスグループ(=job)にシグナルを送信します。いいえこれが起こらないようにしてください。
デフォルトでは、sh -c '...'
「バックグラウンド」を含むすべてのプロセスは同じ操作の一部であり、シェルスクリプトはジョブ制御を実行しません。sleep &
停止するバックグラウンドプロセスグループのメンバーがいない場合はSIGHUP
noを送信します。
$ 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は、SIGHUP
bashがセッションリーダーであるか、ジョブが実行されているか、停止されているかにかかわらず、テーブル内のすべてのジョブ(自己起動して拒否されていないジョブのみ)にaを送信します。
$ bash
$ sh -c 'sleep 555 & trap "echo hupped!" HUP; sleep 666' &
[1] 3413
$ kill -HUP $$
Hangup
hupped!
Hangup
[1] これはとにかく不可能です。setsid()
プロセスは新しいセッションでのみ作成できます。いいえプロセスグループリーダーとして、ジョブ全体を新しいセッションまたは既存のセッションに移動することはできません。
[2] bashのマンページに文書化されています:
SIGHUP
対話型シェルは、終了する前にSIGHUP
実行中または停止したすべてのジョブを再送信します。停止したジョブを送信して受信したことをSIGCONT
確認してくださいSIGHUP
。シェルが特定のジョブにシグナルを送信しないようにするには、組み込みコマンド(以下のシェルの組み込みコマンドを参照)を使用して、ジョブテーブルからそのジョブを削除または受信しないようにマークする必要がdisown
あります。を使用して 。SIGHUP
disown -h
もう一つのshopt -s huponexit
理由はログインbashシェルは終了時にジョブに送信しますHUP
(信号によるものかどうかにかかわらず)。これはまた、オペレーティングシステムの標準的なタスク制御機能と混乱するように重なり合う。