
信頼性の低い Wi-Fi 環境では、SSH 経由でサーバーに接続しなければならないことがよくあります。サーバーでは screen を実行しているので、切断された場合は再接続して screen セッションを再開し、中断したところから再開できますが、接続が失われると依然として大きな時間がかかります。サーバーにいる間に接続が切断されると、ターミナル ウィンドウがフリーズする傾向があります。そのタブを終了し、新しいタブを開き、サーバーに再度 ssh して screen セッションを再開する必要があります。サーバーで screen を実行し、ローカルで screen を実行してこれを試しました。いずれの場合も、接続が切断されるとフリーズする傾向があります。
スクリーンに似たもの、またはスクリーン自体で、自動的に再接続を試み、セッションを実行し続ける方法はありますか? そうすれば、手動で再接続し続ける必要がなくなります。接続が失われる場合、それは非常に短い時間 (おそらく 1 秒未満) だけであることが多いと思います。
私はUbuntu 14.04 LTS、MATEエディションを使用しています。ありがとうございます
答え1
次のような方法を検討できますmosh
:https://mosh.org/
信頼性の高いインターネット接続を使用して「ジャンプ」サーバーを設定し、それを使用してmosh
接続し、管理する各サーバーにセッションを確立することができます。ジャンプ サーバーの使用を推奨する理由は、管理しているサーバーにssh
インストールしたくない場合があるためです。mosh
のもう 1 つの利点は、mosh
TCP ではなく UDP に基づいているため、たとえば WiFi からモバイル インターネット接続に移行するなど、IP アドレスが変更されてもセッションが維持されることです。
明確にしておくと、mosh
は の代わりではなく、 です。 自体は、クライアントが何らかの理由で停止した場合にセッションに再接続する方法を提供しないため、 と一緒に使用することは依然として良い考えです。screen
ssh
screen
mosh
答え2
ServerAlive
接続が失敗したことを検出するには、ssh のオプションを使用します。
ServerAliveCountMax
ssh(1) がサーバからメッセージを受信せずに送信できるサーバ アライブ メッセージ (下記参照) の数を設定します。サーバ アライブ メッセージの送信中にこのしきい値に達すると、ssh はサーバから切断され、セッションが終了します。サーバ アライブ メッセージの使用は TCPKeepAlive (下記) とは非常に異なることに注意してください。サーバ アライブ メッセージは暗号化されたチャネルを介して送信されるため、偽装できません。TCPKeepAlive によって有効になる TCP キープアライブ オプションは偽装可能です。サーバ アライブ メカニズムは、クライアントまたはサーバが接続が非アクティブになったことを知る必要がある場合に便利です。デフォルト値は 3 です。たとえば、ServerAliveInterval (下記参照) が 15 に設定され、ServerAliveCountMax がデフォルトのままになっている場合、サーバーが応答しなくなると、ssh は約 45 秒後に切断されます。
ServerAliveInterval
タイムアウト間隔を秒単位で設定します。この時間が経過すると、サーバーからデータが受信されなくなり、ssh(1) は暗号化されたチャネルを介してメッセージを送信し、サーバーからの応答を要求します。デフォルトは 0 で、これらのメッセージはサーバーに送信されないことを示します。
ServerAliveInterval
したがって、5 に設定すると、ssh
ネットワークが 15 秒間途切れた場合に自動的に切断されます。
答え3
私は使用していますtmux
数年前から使っていますが、私の経験では、自動的に再接続されます。少なくとも、接続が比較的短時間しか切れないときは。私が実際に使っているのはbyobu
tmux
バックエンドとして tmux を使用します。この堅牢性が の機能なのか、あるいは 2 つの組み合わせの機能なのかはわかりませんbyobu
が、両方試してみることをお勧めします。
私はローカルの Arch インストールから VPN 経由でさまざまなリモート Ubuntu サーバーに接続しています。リモートに接続中にネットワーク ケーブルを抜いてテストしたところ、セッションがハングしましたが、ケーブルを再び差し込むとすぐにシームレスに再開しました。
しかし、ルーターを再起動してテストしたところ、接続は戻りませんでした。ネットワークがダウンしていた時間の長さと関係があると思われますが、数秒ダウンしただけであれば再接続されるようです。
関連する場合、私はこれらすべてを次のように行いますterminator
ターミナルエミュレーターとして使用します。
これら 3 つはすべて Ubuntu リポジトリで利用可能です。
sudo apt-get install tmux terminator byobu
tmux
ただし、 またはのどちらが SSH 切断の処理に適しているかはまったくわかりませんbyobu
。私の経験では、短時間の接続切断から復旧することが多いということだけはわかっています。ただし、これは私の設定の他の側面によるものである可能性があります。
答え4
免責事項
SSH接続が短時間のネットワーク停止に耐えられない場合は、その他ssh
TCP が通常の動作を実行できない状態が続いています。
詳細については以下を参照してください。とにかく:
最も迅速で簡単な方法
次のようなシェル スクリプトを作成します。
#!/bin/sh -
# Tune these numbers depending on how aggressively
# you want your SSH session to get reconnected.
timeout_options='-o ServerAliveInterval=4 -o ServerAliveCountMax=2'
# 255 is the status OpenSSH uses to signal SSH errors, which
# means we want to connect. All other exit statuses suggest
# an intentional exit.
status=255
# Keep opening the SSH connection and immediately dropping into
# `screen` until an intentional exit happens.
while [ "$status" = 255 ]
do
ssh $timeout_options -t "$@" screen -dR
status=$?
# You can add a `sleep` command here or a counter or whatever
# you might need as far as rate/retry limiting.
done
exit "$status"
ssh
これは、 との接続とアタッチを試行し続ける単純なループを実行するだけですscreen
。 ホストまたは通常ssh
呼び出しに渡すその他のものをコマンドライン引数として渡します。
再接続は、SSH が接続に関するエラーを報告するかどうかに基づいて行われるため、「WiFI がオンになっていません」などの SSH 以外のエラーを検出するインテリジェンスはありませんが、これはおそらく問題ではありません。
ssh-agent
追加の入力なしで再接続が機能するパスフレーズなしの SSH キーを持っていると想定しています。
^C
再接続中に人間が感知できないほんの一瞬の間に押すと、^C
クライアント端末に渡すのではなくスクリプトを強制終了してしまうという小さな競合状態が発生する可能性があるため、接続がハングしていると思われる場合は、あまり熱心に押し込まないでください^C
。
最もシンプルな追加ソフトウェアソリューション
プログラムを試すことができますオートこれは、Ubuntu パッケージ リポジトリで利用できるはずです。
ソースからビルドしたり監査したりする必要がある場合、これは追加のライブラリを依存せずにコンパイルされる単一のCプログラムであり、上記の私のハックよりも接続の有効性をチェックするインテリジェンスが優れているようです。そしてrscreen
また、に自動的にアタッチされる便利なスクリプト コマンドも付属していますscreen
。
詳細
ssh
通常の回復方法
確認のため、自分で確認せずに発言するのは好きではないので、回答する前にちょっとしたテストを実行しました。
LinuxデバイスでWiFiに接続し、LAN上の別のデバイスにSSH接続し、ssh
もう一方の端との接続が機能していることを確認しました(コマンドなどを実行できました)。その後、クライアントでWiFiを切断しました(インターフェイスが構成解除され、IP アドレスがなくなる)、ssh セッションにさらにたくさんの文字を入力し (もちろん応答なし)、WiFi に再接続しました。信号不良などの要因により、再接続は実際には少なくとも 1 回失敗し、最終的に再接続されました。セッションがssh
回復するまで約 5 秒間待機しましたが、何も起こらなかったため、もう 1 つキーを押すと、ssh
セッションがすぐに再開され、切断中に入力したすべてのキーがコマンド ラインに表示されました。
ssh
OSが何か問題があったと伝えるまで、TCPネットワークソケットに書き込み/読み込みを行うだけで、TCPは実際にはとても長時間の接続切断にも耐えます。
Linux の TCP スタックは、デフォルトのカーネル設定で独自のデバイスに任せておくと、接続が完全に無音になっても何分も問題なく許容し、その後、接続が切断されたと宣言してエラーを報告しますssh
。最終的に諦めるまでに、およそ 30 分程度かかります。少なくとも、1 秒または 1 分間続く接続の中断に耐えるには十分な時間です。
ただし、内部的には、Linux TCP スタックが徐々に長い遅延でメッセージを再試行するため、接続が復旧するまでに、セッションがssh
再び「アクティブ」になる前にさらに遅延が発生する可能性があります。
なぜこれが時々壊れるのか
多くの場合、何らかの原因で接続が閉じられてしまうことがあります。大幅に短くなるTCP スタックが許容する量よりも長い非アクティブ期間が続き、その接続状態をクライアントに報告できないことがありますssh
。
可能性のある候補は次のとおりです。
ファイアウォールやNATルーターは、メモリを使用して各TCP接続を記憶する必要があります。最適化とDOS攻撃の緩和策として、時には忘れる接続し、黙って無視する接続が存在することを覚えていない場合、接続の途中にあるパケットは無効に見えるため、その結果生じるパケットは無効になります。
より適切に動作するファイアウォール/ルーターは、通常
connection reset by peer
エラー メッセージとして現れる TCP RST パケットを挿入しますが、リセット パケットはファイア アンド フォーゲットであるため、その時点でクライアントへの接続にまだ問題があり、リセット パケットもドロップされた場合、クライアントは接続がまだ有効であると認識します。サーバー自体予期しないパケットを黙ってドロップするファイアウォール ポリシーが設定されている可能性があります。この場合、サーバーが接続が閉じたと認識しているのにクライアントがそう認識していないときは、クライアントの接続再開の試みが中断されます。つまり、クライアントは接続を継続しようとしますが、サーバーのファイアウォール状態にはこれらのパケットが属するアクティブな接続がないため、サーバーはそれを無視します。
Linuxを使っているなら、サーバーの
iptables
/ip6tables
(またはnft
新しいものを使用している場合)で、何を許可し、何を削除しているのかを注意深く確認してください。新しい/設立/関連しているTCP SSHポート上のパケットですが、ない「無効な」もの - 許可されていないものをすべて黙ってドロップすると、この一般的な設定により、短時間の接続の問題の後にこのようなフリーズが発生する可能性があります。SSH サーバー自体は、TCP または SSH クライアントのキープアライブ パケットの OpenSSH オプションの 1 つを使用して、一定時間非アクティブになると接続を閉じるように設定されている可能性があります。これ自体は無期限のハングを引き起こすことはありませんが、上記のいずれかの状態になる可能性があります。
ssh
セッションがハングアップする状態になった後、自動的に「ハングアップ解除」するのに十分な時間を与えていない可能性があります。