組み込みシステムがあります。その上でtelnet
を実行してから、アプリケーションをバックグラウンドで実行します。
./app_name &
端末を閉じて他の端末からtelnet
を実行し、確認すると、このプロセスがまだ実行中であることがわかります。
これを確認するために、小さなプログラムを作成しました。
#include<stdio.h>
main()
{
while(1);
}
このプログラムをローカルのLinux PCでバックグラウンドで実行し、ターミナルを閉じました。
今、他の端末からこのプロセスをチェックしたところ、このプロセスも強制終了されていることがわかりました。
私の質問は:
通常、フォアグラウンドジョブとバックグラウンドジョブは、さまざまな状況でカーネルまたはシェルから送信されたSIGHUP
によって強制終了されます。
SIGHUP
を送信しますか?KernelはSIGHUP
を controlling process に送信します:
KernelはSIGHUP
を他のプロセスグループに送信します。
制御プロセスは、制御端末への接続を確立したセッションリーダーです。
通常、制御プロセスはシェルです。要約すると、
SIGHUP
をシェルに送信します。SIGHUP
をフォアグラウンドプロセスグループに送信します。SIGHUP
を送信します。カーネルは、停止したプロセスが含まれていない場合、バックグラウンドプロセスグループにSIGHUP
を送信しないことに注意してください。
bash
はいつSIGHUP
を送信しますか?BashはSIGHUP
をallジョブ(フォアグラウンドおよびバックグラウンド)に送信します:
SIGHUP
を受信し、対話型のシェルである(およびジョブ制御サポートがコンパイル時に有効になっている場合);huponexit
オプションが設定されます(およびジョブ制御サポートがコンパイル時に有効になります)。詳細はこちら こちら 。
ノート:
bash
は送信しないSIGHUP
をdisown
を使用してジョブリストから削除したジョブに送信します。Nohup
ignoreSIGHUP
を使用して開始されたプロセス。詳細 こちら 。
通常、シェルはSIGHUP
を伝播します。通常の終了時にSIGHUP
を生成することはあまり一般的ではありません。
TelnetまたはSSHの場合、接続が閉じられると(たとえば、PCでtelnet
ウィンドウを閉じると)次のようになります。
SIGHUP
をbash
に送信します。bash
はSIGHUP
を受信し、SIGHUP
をすべてのジョブに送信して終了します。SIGHUP
を受け取り、終了します。bash
またはtelnetd
SSHサーバーからbusybox
およびdropbear
を使用して問題を再現できます:sometimes、クライアント接続が閉じられると、バックグラウンドジョブはSIGHUP
を受け取りません(そして終了しません)。
サーバー(telnetd
またはdropbear
)がptyのマスター側を閉じると、競合状態が発生するようです:
bash
はSIGHUP
を受け取り、バックグラウンドジョブを(予期したとおりに)即座に強制終了して終了します。bash
は、ptybeforeがEOF
を処理する前に、スレーブ側でSIGHUP
を検出することがあります。bash
がEOF
を検出すると、デフォルトではSIGHUP
を送信せずにすぐに終了します。そして、バックグラウンドジョブは実行中のままです!
通常の出口(bash
を含む)でSIGHUP
を送信するようにEOF
を構成することもできます。
bash
がlogin Shellとして開始されていることを確認します。 huponexit
works ログインシェルの場合のみ、AFAIK。
ログインシェルは、-l
オプションまたはargv[0]
の- 先頭のハイフン で有効にします。ログインシェルモードで/bin/bash -l
を呼び出す/bin/login
以上の/bin/sh
を実行するようにtelnetd
を設定できます。
例えば。:
telnetd -l /bin/login
huponexit
オプションを有効にします。
例えば。:
shopt -s huponexit
毎回これをbash
セッションに入力するか、.bashrc
または/etc/profile
に追加します。
bash
は、安全な場合にのみ信号のブロックを解除し、一部のコードセクションを信号ハンドラーによって安全に中断できない場合に信号をブロックします。
そのようなクリティカルセクションは中断ポイントを時々呼び出し、クリティカルセクションが実行されるときにシグナルが受信されると、そのハンドラーは次の中断ポイントが発生するか、クリティカルセクションが終了するまで遅延します。
ソースコードの quit.h
から掘り始めることができます。
したがって、私たちの場合、bash
はクリティカルセクションにあるときにSIGHUP
を受け取ることがあります。 SIGHUP
ハンドラーの実行が遅延し、bash
がEOF
を読み取り、クリティカルセクションを終了するか、次の割り込みポイントを呼び出すbeforeの前に終了します。
ターミナルを閉じると、ShellはSIGHUP
をすべてのバックグラウンドプロセスに送信し、それによってプロセスが強制終了されます。これは、いくつかの方法で抑制できます。最も顕著な例は次のとおりです。
Nohup
を指定してプログラムを実行すると、SIGHUP
をキャッチしてプログラム出力をリダイレクトします。
$ Nohup app &
disown
は、シェルにSIGHUP
を送信しないように指示します
$ app &
$ disown
シェルによって異なります。上記は少なくともbashに適用されます。
何が起こっているのかを完全に理解するには、unix
内部に少し入る必要があります。
このようなコマンドを実行しているとき
./app_name &
app_name
がバックグラウンドプロセスグループに送信されます。 unix
プロセスグループについて確認できます ここ
通常の終了でbash
を閉じると、すべてのジョブに対してSIGHUP
ハングアップシグナルがトリガーされます。 unix
ジョブ制御に関するいくつかの情報は here です。
bash
の終了時にアプリを実行し続けるには、Nohup
ユーティリティを使用して、アプリがハングアップシグナルの影響を受けないようにする必要があります。
Nohup-ハングアップの影響を受けないコマンドを実行し、非ttyに出力します
そして最後に、これはあなたがそれを行う必要がある方法です。
Nohup app_name & 2> /dev/null;
どちらの場合もAFAIKはプロセスを強制終了する必要があります。これを回避するには、次のようなNohupを発行する必要があります。
> Nohup ./my_app &
このようにして、プロセスは実行を継続します。おそらくtelnetの部分は、次のようなバグが原因です。