web-dev-qa-db-ja.com

SSHセッションから切断されるとプログラムが終了しますか?

したがって、rsyncまたはcpまたは長時間実行できるその他のコマンドを開始した後、SSHセッションから切断されたとしましょう。切断されてから終了するまで、そのコマンドは実行し続けますか、それとも強制終了されますか?

いつもこれを疑問に思いました。

92
fregas

2016年の編集:

このQ&Aは systemd v230 debacle より前のものです。 systemd v230以降、新しいデフォルトでは、これを防ぐために歴史的に有効な予防策が講じられたものに関係なく、終了するログインセッションのすべての子が強制終了されます。この動作は、KillUserProcesses=no/etc/systemd/logind.confを設定することで変更できます。または、ユーザー空間でデーモンを起動するためのsystemd固有のメカニズムを使用して回避できます。これらのメカニズムは、この質問の範囲外です。

以下のテキストは、Linuxが存在するよりも長い間、物事がUNIXデザインスペースで伝統的に機能してきた方法を説明しています。


彼らは殺されるでしょうが、必ずしもすぐにではありません。これは、SSHデーモンが接続が停止していると判断するのにかかる時間に依存します。以下は、実際にどのように機能するかを理解するのに役立つ長い説明です。

ログインすると、SSHデーモンが疑似端末を割り当て、ユーザーの構成済みログインシェルに接続しました。これは制御端末と呼ばれます。その時点で通常起動するすべてのプログラムは、シェルの深さがいくつであっても、最終的にはその祖先をそのシェルまでたどります。これはpstreeコマンドで確認できます。

接続に関連付けられたSSHデーモンプロセスは、接続が停止していると判断すると、ハングアップシグナル(SIGHUP)をログインシェルに送信します。これにより、シェルが消滅したこと、およびシェル自体のクリーンアップを開始する必要があることがシェルに通知されます。この時点で起こることはシェル固有です( "HUP"のドキュメントページを検索してください)が、ほとんどの場合、終了する前に関連する実行中のジョブにSIGHUPを送信し始めます。次に、これらの各プロセスは、その信号を受信したときに実行するように構成されていることをすべて実行します。通常、これは終了することを意味します。それらの仕事に独自の仕事がある場合、信号もしばしば渡されます。

制御端末のハングアップを乗り越えたプロセスは、端末(その内部で開始したデーモンプロセス)から切り離されたプロセス、または接頭辞Nohupコマンドで呼び出されたプロセスです。 (つまり、「これでハングアップしないでください」)デーモンはHUP信号を異なる方法で解釈します。それらには制御端末がなく、HUP信号を自動的に受信しないため、代わりに、管理者からの手動要求として再構成され、構成を再ロードします。皮肉なことに、これは、ほとんどの管理者が、デーモンでない場合のこの信号の「ハングアップ」の使用法を、ずっと後まで学習しないことを意味します。これがあなたがこれを読んでいる理由です!

端末マルチプレクサは、シェル環境を切断間でそのまま維持する一般的な方法です。切断が偶発的であるか意図的であるかに関係なく、後で再接続できる方法でシェルプロセスから切り離すことができます。 tmuxscreenはより人気のあるものです。それらを使用するための構文はあなたの質問の範囲を超えていますが、それらは調べる価値があります。


SSHデーモンが接続が停止していると判断するまでにかかる時間について、詳しく説明するように要請されました。これは、SSHデーモンのすべての実装に固有の動作ですが、いずれかの側がTCP接続をリセットすると、それらすべてが終了することを期待できます。これは、サーバーがソケットに書き込むとTCP=パケットは確認されません、または何もPTYに書き込もうとしていない場合はゆっくりです。

この特定のコンテキストでは、書き込みをトリガーする可能性が最も高い要因は次のとおりです。

  • サーバー側のPTYに書き込もうとするプロセス(通常はフォアグラウンドにあるプロセス)。 (サーバー->クライアント)
  • クライアント側でPTYに書き込もうとしているユーザー。 (クライアント->サーバー)
  • あらゆる種類のキープアライブ。これらは通常、クライアントまたはサーバーのどちらでもデフォルトでは有効になっていません。通常、アプリケーションレベルとTCPベース(つまりSO_KEEPALIVE)の2つのフレーバーがあります。キープアライブはいずれかになります。サーバーまたはクライアントは、他に何もソケットに書き込む理由がない場合でも、反対側にパケットを頻繁に送信しません。これは通常、接続のタイムアウトが速すぎるファイアウォールを回避することを目的としていますが、送信側は、反対側がそれほど迅速に応答していないときに通知します。

TCPセッションの通常のルールがここに適用されます。クライアントとサーバー間の接続に中断があり、問題の発生時にどちらの側もパケットを送信しようとしない場合、両方の接続が存続します。サイドは後で応答し、予期されるTCPシーケンス番号を受け取ります。

片方の側でソケットが停止していると判断した場合、通常はすぐに影響が出ます。sshdプロセスがHUPを送信して自己終了するか(前述のとおり)、またはクライアントが検出された問題をユーザーに通知します。片方がもう片方が死んでいると思っているからといって、もう片方がこのことを通知されているとは限らないことに注意してください。接続の孤立した側は、書き込みを試みてタイムアウトするか、TCPリセットが反対側から受信されるまで(通常、接続が利用可能であった場合)まで、開いたままになります。この回答で説明されているクリーンアップは、serverが気付いた場合にのみ行われます。

120
Andrew B

他の人が述べたように、いったんSSHから切断すると、その中で実行されているものはすべて失われます。

@ Michael Hampton や他の人が述べたように、tmuxscreenなどのツールを使用して、コンテンツ(つまり、子プロセス)を失うことなく端末への接続を切断/再接続できます。

さらに、アンパサンド&を使用してプロセスをバックグラウンドに配置し、コマンドdisownを使用して現在のシェルとの関連付けを解除できます。

# start a command
% sleep 5000 &
[1] 3820

# check it
% jobs
[1]+  Running                 sleep 5000 &

# disown everything
% disown -a

# check it again (gone from Shell)
% jobs
%

# but it's still running on the system
% ps -eaf|grep "[s]leep"
saml      3820 23791  0 00:16 pts/1    00:00:00 sleep 5000
%
23
slm

いいえ、まだターミナルに接続されていて、Nohupのようなものでバックグラウンドに配置されていないプログラムはすべて強制終了されます。

これがtmuxや古いscreenなどの仮想端末ソリューションがあり、切断された場合でも実行を継続し、後で再接続できるセッションを作成する理由です。

14
Michael Hampton