web-dev-qa-db-ja.com

ログアウト時にSIGHUPがジョブに送信されないのはどの場合ですか?

実行していると主張したユーザーからの回答を読んだ

foo 2>&1 >& output.log &

ログアウトした場合でもfooは引き続き実行されます。このユーザーによると、これはSSH接続でも機能しました。

SSHから切断したり、TTYを終了したりすると、シェルとそのプロセスがSIGHUPを受信して​​終了するという印象を受けたので、本当に信じていませんでした。私の想定では、これがそのような場合にNohup、またはtmuxscreenなどを使用する唯一の理由でした。

次に glibcのマニュアルを調べました

このシグナルは、端末上の制御プロセスの終了を、そのセッションに関連付けられたジョブに報告するためにも使用されます。この終了により、セッション内のすべてのプロセスが制御端末から効果的に切断されます。

これは私の考えを裏付けるようです。しかし、さらに見ると、 それは言います

プロセスが制御端末を持つセッションリーダーである場合、SIGHUPシグナルがフォアグラウンドジョブの各プロセスに送信され、制御端末はそのセッションから切り離されます。

それで、これはバックグラウンドで実行されたジョブがSIGHUPを受け取ることを意味しますか?

さらに混乱したのは、対話型のZshセッションを実行してyes >& /dev/null &を実行し、exitと入力したとき、Zshがジョブの実行を警告し、exitを2回入力した後、1つのジョブをSIGHUPしたことを通知した。 Bashでまったく同じことを行うと、ジョブが実行されたままになります…

10
slhck

BashはSIGHUPを自分自身がSIGHUPを受信した場合にのみ送信するようです。これは、たとえば仮想端末が閉じられたとき、またはSSH接続が中断されたときに発生します。 ドキュメント から:

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

したがって、exitと入力するか、 Ctrl+D これはBashにハングアップ信号を送信しないため、すべてのバックグラウンドプロセスが残ります。

Bashに、実行中のバックグラウンドプロセスがまだあるという事実について警告するように強制できます。

shopt -s checkjobs

対話型シェル( ここを参照 )を使用している場合、終了時にSIGHUPを送信するオプションがあります。しかし、Bash 4.2.25がインストールされている私のマシンでは動作しません。多分それはあなたのために働く

shopt -s huponexit
18
Raphael Ahrens