web-dev-qa-db-fra.com

Pourquoi les consoles se bloquent-elles parfois pour toujours lorsque la connexion SSH est interrompue?

J'ai vu cela avec tant de consoles (sur Linux, Mac, ...), et avec beaucoup de machines différentes dans de nombreux réseaux différents. Je ne peux jamais identifier la raison exacte, pourquoi cela se produit: Tout ce que vous avez à faire est de vous connecter à une machine via SSH. Si la connexion est interrompue pour une raison quelconque (pour simplifier, disons que le câble réseau a été tiré), la console se bloque parfois pour toujours - à d'autres moments, elle se termine très bien pour le shell parent.

C'est tellement ennuyeux lorsque cela se produit (par exemple, vous perdez l'historique des commandes.) Y a-t-il peut-être un raccourci clavier secret qui peut forcer une sortie (Ctrl-C ou Ctrl-D ne fonctionne pas)? Et quelle est la raison de ce "bug" aléatoire dans toutes les implémentations?

96
Chris Lercher

Il existe un raccourci clavier "secret" pour forcer une sortie: ~) À partir de la session gelée, appuyez sur ces touches dans l'ordre: Enter~. Le tilde (uniquement après une nouvelle ligne) est reconnu comme une séquence d'échappement par le client ssh, et la période indique au client de mettre fin à ses affaires sans plus tarder.

Le comportement de longue haleine sur les problèmes de communication n'est pas un bug, la session SSH traîne en espérant que l'autre côté reviendra. Si le réseau tombe en panne, parfois même des jours plus tard, vous pouvez récupérer une session SSH. Bien sûr, vous pouvez lui dire spécifiquement d'abandonner et de mourir avec la séquence ci-dessus. Vous pouvez également effectuer diverses opérations, telles que la définition de délais d'expiration pour votre client afin que s'il ne dispose pas d'un lien actif pendant un certain temps, il s'éteigne de lui-même, mais le comportement par défaut est de rester connecté que possible!

Edit: Une autre application utile de cette touche d'interruption est d'attirer l'attention du client ssh local et de la faire un arrière-plan pour revenir à votre shell local pendant une minute - dire pour obtenir quelque chose de votre historique - puis forground pour continuer à travailler à distance. Enter~Ctrl+Z pour envoyer le client ssh dans la file d'attente des travaux en arrière-plan de votre shell local, puis fg comme d'habitude pour le récupérer.

Edit: Lorsque vous traitez des sessions SSH imbriquées, vous pouvez ajouter plusieurs caractères tilde pour ne sortir que d'une des sessions SSH de la chaîne, mais conserver les autres. Par exemple, si vous êtes imbriqué dans 3 niveaux, (c'est-à-dire que vous ssh de local-> Machine1-> Machine2-> Machine3), Enter~. vous ramènera à votre session locale, Enter~~. vous laissera dans Machine1, et Enter~~~. vous laissera dans Machine2. Cela fonctionne également pour d'autres séquences d'échappement, comme le déplacement temporaire de la session ssh en arrière-plan. Ce qui précède fonctionne pour n'importe quel niveau d'imbrication, en ajoutant simplement plus de tilde.

Enfin, vous pouvez utiliser Enter~? pour imprimer un menu d'aide des commandes d'échappement disponibles.

TL; DR - les commandes d'échappement prises en charge sont des séquences d'échappement prises en charge:

 ~.   - terminate connection (and any multiplexed sessions)
 ~B   - send a BREAK to the remote system
 ~C   - open a command line
 ~R   - request rekey
 ~V/v - decrease/increase verbosity (LogLevel)
 ~^Z  - suspend ssh
 ~#   - list forwarded connections
 ~&   - background ssh (when waiting for connections to terminate)
 ~?   - this message
 ~~   - send the escape character by typing it twice
(Note that escapes are only recognized immediately after newline.)
150
Caleb

SSH offre une installation permanente. Ajoutez les éléments suivants à votre ~/.ssh/config (créer s'il n'existe pas):

ServerAliveInterval 15
ServerAliveCount 3

Ce paramètre établira un signal de maintien en vie envoyé toutes les 15 secondes à travers le tunnel sécurisé. Après trois échecs consécutifs, le client SSH se fermera.

Notez que sur certains systèmes (y compris macOS 10.14), il doit plutôt être:

ServerAliveInterval 15
ServerAliveCountMax 3

Tiré de cette réponse sur ask.ubuntu: https://askubuntu.com/a/29967/30266

14
krlmlr

Le fait qu'il se bloque est une fonction de TCP, pas de SSH. L'application n'a aucun moyen de savoir que la session/connexion TCP a été rompue, sauf si TCP informe l'application utilisant la connexion que la connexion n'existe plus. De du point de vue de chaque hôte, la session TCP est toujours à l'état Établi et il n'y a rien à dire qu'une longue session inactive (aucun flux de données) n'est valide autre qu'un RST ou un manque de réponse à un TCP paquet keepalive (qui n'est pas implémenté universellement). Cela ne semble pas être un bogue dans SSH pour moi, je m'attendrais à ce comportement.

9
joeqwerty

Si la connexion est correctement suspendue, aucune frappe magique ne sera effectuée car la connexion est déjà suspendue avant d'appuyer sur les touches. Vous pouvez dire au client de se terminer, mais cela n'affectera pas l'historique conservé (ou non) du côté serveur.

Bien que cela ne réponde pas réellement à la question, cela peut aider à réduire les effets d'un blocage de connexion: lorsque je travaille à distance (et même généralement quand je ne le suis pas), je passe par screen (avec ou sans le byobu wrapper en fonction de sa disponibilité) afin que s'il y a une sorte de connexion, ma session, avec tout son historique, soit conservée et disponible dans l'état où je l'ai laissée lorsque je me reconnecte.

5
David Spillett

Dans mon cas, le problème était en grande taille MTU. Vous pouvez changer MTU sur le routeur si vous utilisez NAT, mais je change MTU sur le serveur:

Sudo /sbin/ifconfig eth0 mtu 1036
Sudo /etc/init.d/networking restart

Sous Windows, vous pouvez également augmenter cette clé:

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters]
"TcpMaxDataRetransmissions"=dword:00000010
0
Vasin Yuriy