Warum bleiben Konsolen manchmal für immer hängen, wenn die SSH-Verbindung unterbrochen wird?

89

Ich habe das mit so vielen Konsolen (unter Linux, Mac, ...) und mit vielen verschiedenen Computern in vielen verschiedenen Netzwerken gesehen. Ich kann nie genau sagen, warum dies passiert: Sie müssen sich nur über SSH bei einem Computer anmelden. Wenn die Verbindung aus irgendeinem Grund unterbrochen wird (der Einfachheit halber wird beispielsweise das Netzwerkkabel gezogen), hängt die Konsole manchmal nur für immer, in anderen Fällen wird sie einfach zur übergeordneten Shell beendet.

Es ist so ärgerlich, wenn dies passiert (z. B. wenn Sie den Befehlsverlauf verlieren). Gibt es möglicherweise eine geheime Tastenkombination, die ein Beenden erzwingen kann (Strg-C oder Strg-D funktionieren nicht)? Und was ist der Grund für diesen zufälligen "Fehler" bei allen Implementierungen?

Chris Lercher
quelle
Dieser Thread scheint angemessen zu sein, um Mosh (Mobile Shell) zu erwähnen, das sich gut mit Verbindungsfehlern befasst, einschließlich Roaming (IP-Änderung) und anderen Dingen.
Ciprian Tomoiagă

Antworten:

137

Es gibt eine "geheime" Tastenkombination, um das Beenden zu erzwingen: ~) Enter~.Drücken Sie in der eingefrorenen Sitzung die folgenden Tasten in der angegebenen Reihenfolge: Die Tilde (nur nach einem Zeilenumbruch) wird vom ssh-Client als Escape-Sequenz erkannt, und der Punkt gibt die an Client, um sein Geschäft ohne weiteres zu beenden.

Das Langzeitverhalten bei Kommunikationsproblemen ist kein Fehler. Die SSH-Sitzung bleibt in der Hoffnung, dass die andere Seite zurückkommt. Wenn das Netzwerk ausfällt, können Sie manchmal sogar Tage später eine SSH-Sitzung zurückerhalten. Natürlich können Sie es ausdrücklich anweisen, mit der obigen Reihenfolge aufzugeben und zu sterben. Es gibt auch verschiedene Möglichkeiten, wie z. B. das Festlegen von Keep-Alive-Zeitlimits in Ihrem Client, damit er selbstständig heruntergefahren wird, wenn er eine bestimmte Zeit lang keinen aktiven Link hat, aber standardmäßig so bleibt verbunden wie möglich!

Bearbeiten: Eine weitere nützliche Anwendung dieses Interrupt-Schlüssels besteht darin, die Aufmerksamkeit des lokalen SSH-Clients auf sich zu ziehen und ihn im Hintergrund für eine Minute auf Ihre lokale Shell zurückzuführen. Enter~ Ctrl+ Z, um den ssh-client in die Warteschlange des Hintergrundjobs Ihrer lokalen Shell zu schicken und ihn dann fgwie gewohnt zurück zu bekommen.

Bearbeiten: Wenn Sie mit verschachtelten SSH-Sitzungen arbeiten, können Sie mehrere Tilde-Zeichen hinzufügen, um nur aus einer der SSH-Sitzungen in der Kette auszubrechen, die anderen jedoch beizubehalten. Wenn Sie zum Beispiel in 3 Ebenen verschachtelt sind (dh von local-> Machine1-> Machine2-> Machine3 aus ssh), kehren Enter~.Sie zu Ihrer lokalen Sitzung zurück, Enter~~.lassen Sie in Machine1 und Enter~~~.in Machine2 zurück . Dies funktioniert auch für andere Escape-Sequenzen, z. B. das temporäre Verschieben der ssh-Sitzung in den Hintergrund. Das Obige funktioniert für jede Verschachtelungsebene, indem einfach mehr Tilden hinzugefügt werden.

Abschließend können Sie Enter~?ein Hilfemenü mit verfügbaren Escape-Befehlen ausdrucken.

TL; DR - Die unterstützten Escape-Befehle sind Unterstützte Escape-Sequenzen:

 ~.   - 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.)
Caleb
quelle
11
+1 für die Kenntnis des Kennworts für die geheime Dodekoppelprüfung, um sshd in den Kopf zu schießen. Haben Sie es auf die gleiche Weise wie ich herausgefunden (Tippfehler, ~/.somethingorothernachdem Sie die Eingabetaste gedrückt haben )?
Voretaq7
2
@ voretaq7: Nein, ich war nicht so schlau, aber als mich jemand darauf aufmerksam machte, sagte ich: "Wirklich? Das geschah also all die Male, in denen meine Muschel nur knallte! Ohne Grund, als ich tippte?" . Es ist keine übliche Abfolge, außer in den von Ihnen genannten Fehlern, aber es kann vorkommen.
Caleb
14
Wobei "geheim" er "in der Manpage" bedeutet.
Larsks
4
Während viele Leute nicht darüber Bescheid wissen, ist es im Klartext wirklich ein Geheimnis. man sshbehandelt dies unter dem ESCAPE CHARACTERSAbschnitt. ~.(Trennen) und ~^Z(Hintergrund ssh) sind sehr praktisch.
Stefan Lasiewski
9
Natürlich steht es auf der Manpage :) Ich habe nur das Wort secret verwendet, weil das OP es tat, und ich habe die Zunge in die Wange gedrückt. Das Problem bei dieser Funktion ist, dass die Benutzer nicht wissen, wo sie danach suchen sollen. Sie erwarten, dass Steuerzeichen und solche Signale Teil der Shell oder dergleichen sind. Sobald Sie wissen, wo Sie suchen müssen oder was Sie fragen müssen, ist es natürlich da.
Caleb
12

SSH bietet eine Keep-Alive-Funktion. Fügen Sie Folgendes zu Ihrem lokalen hinzu ~/.ssh/config(erstellen, wenn es nicht vorhanden ist):

ServerAliveInterval 15
ServerAliveCount 3

Mit dieser Einstellung wird ein Keep-Alive-Signal eingerichtet, das alle 15 Sekunden durch den sicheren Tunnel gesendet wird. Nach drei aufeinanderfolgenden Fehlern wird der SSH-Client beendet.

Beachten Sie, dass auf einigen Systemen (einschließlich macOS 10.14) stattdessen Folgendes erforderlich ist:

ServerAliveInterval 15
ServerAliveCountMax 3

Entnommen aus dieser Antwort auf ask.ubuntu: https://askubuntu.com/a/29967/30266

krlmlr
quelle
9

Die Tatsache, dass es hängt, ist eine Funktion von TCP, nicht von SSH. Die Anwendung kann nicht wissen, dass die TCP-Sitzung / -Verbindung getrennt wurde, es sei denn, TCP teilt der Anwendung über die Verbindung mit, dass die Verbindung nicht mehr besteht. Aus der Sicht der einzelnen Hosts befindet sich die TCP-Sitzung noch im Status "Established" und es gibt nichts zu sagen, dass eine lange inaktive Sitzung (kein Datenfluss) nur als RST-Sitzung oder fehlende Antwort auf ein TCP-Keepalive-Paket gültig ist (was z ist nicht universell implementiert). Das scheint mir kein Fehler in SSH zu sein, ich würde dieses Verhalten erwarten.

Joeqwerty
quelle
5

Wenn die Verbindung ordnungsgemäß aufgehängt ist, wird kein Tastendruck ausgeführt, da die Verbindung bereits aufgehängt ist, bevor Sie die Taste drücken. Sie können dem Client mitteilen, dass er beendet werden soll, dies hat jedoch keine Auswirkungen auf den Verlauf, der am Serverende gespeichert ist (oder nicht).

Dies beantwortet zwar nicht die Frage, kann aber die Auswirkungen eines Verbindungsabbruchs verringern: Wenn ich aus der Ferne arbeite (und normalerweise auch nicht), durchlaufe ich screen(mit oder ohne byobuWrapper, je nach Verfügbarkeit) Wenn also eine Verbindung besteht, wird meine Sitzung mit dem gesamten Verlauf beibehalten und ist in dem Zustand verfügbar, in dem ich sie beim erneuten Herstellen der Verbindung verlassen habe.

David Spillett
quelle
6
Ihr Vorschlag zum Bildschirm ist in Ordnung, aber das erste Bit ist für das Problem tatsächlich nicht zutreffend. Sie müssen die Schlüssel nicht an die entfernte Seite weiterleiten, sondern nur an den LOCAL ssh-Client! Der OP will seine örtliche Hülle inklusive Geschichte zurückhaben. SSH übernimmt es und reagiert nicht auf normale Unterbrechungssequenzen wie STRG-C, weil es diese weitergibt. Es gibt eine Möglichkeit, durch den lokalen Client zu kommen und ihn zu beenden, siehe meine Antwort. Der Verlauf auf der lokalen Seite wird normalerweise trotzdem gespeichert, wenn Sie sich erneut anmelden, abhängig von der Shell-Konfiguration.
Caleb
2
@Caleb: Die Frage, die speziell den Verlust des Verlaufs erwähnt, und der Befehlsverlauf werden serverseitig gespeichert. Um dem Server mitzuteilen, dass er mit dem Verlauf etwas anderes machen soll, müssen Sie eine Nachricht an den Server senden, damit er mit dem Verlauf etwas anderes machen soll. Natürlich gibt es Möglichkeiten, Bash (und einige andere Shells) dazu zu bringen, Verlaufszeilen sofort aufzuzeichnen, anstatt sie im RAM zu sammeln, bis der Benutzer die Shell mit exit/ richtig existiert, die logoutdas Verlaufsproblem lösen würde, ohne sie zu verwenden screen.
David Spillett