Perché le console a volte si bloccano per sempre quando si interrompe la connessione SSH?


89

L'ho visto con così tante console (su Linux, Mac, ...) e con molte macchine diverse in molte reti diverse. Non riesco mai a individuare il motivo esatto, perché questo accade: tutto quello che devi fare è accedere a una macchina tramite SSH. Se la connessione si interrompe per qualche motivo (per semplicità, supponiamo che il cavo di rete sia stato tirato), a volte la console si blocca per sempre - altre volte, esce semplicemente dalla shell genitore.

È così fastidioso quando questo accade (ad es. Perdi la cronologia dei comandi.) C'è forse una scorciatoia da tastiera segreta che può forzare un'uscita (Ctrl-C o Ctrl-D non funzionano)? E qual è la ragione di questo "bug" casuale in tutte le implementazioni?


Questo thread sembra appropriato menzionare Mosh (Mobile Shell) che si occupa bene degli errori di connessione, incluso il roaming (cambio di IP) e altre cose.
Ciprian Tomoiagă,

Risposte:


138

Esiste una scorciatoia da tastiera "segreta" per forzare un'uscita: ~) Dalla sessione congelata, premi questi tasti in ordine: Enter~.La tilde (solo dopo una nuova riga) viene riconosciuta come sequenza di escape dal client ssh e il periodo dice al cliente per chiudere la sua attività senza ulteriori indugi.

Il comportamento a lungo sospeso sui problemi di comunicazione non è un bug, la sessione SSH è in attesa sperando che l'altro lato torni. Se la rete si interrompe, a volte anche giorni dopo è possibile ottenere una sessione SSH. Ovviamente puoi dirlo in modo specifico di arrendersi e morire con la sequenza sopra. Ci sono anche varie cose che puoi fare come impostare timeout keep-alive nel tuo client in modo che se non ha un collegamento attivo per un certo periodo di tempo si spenga da solo, ma il comportamento predefinito è di rimanere come collegato il più possibile!

Modifica: Un'altra utile applicazione di questa chiave di interruzione è attirare l'attenzione del client ssh locale e metterlo in background per tornare alla shell locale per un minuto, per esempio per ottenere qualcosa dalla tua cronologia, quindi metterlo a terra per continuare a lavorare in remoto. Enter~ Ctrl+ Zper inviare il client ssh alla coda dei lavori in background della shell locale, quindi fgnormalmente per ripristinarlo.

Modifica: quando si ha a che fare con sessioni SSH nidificate, è possibile aggiungere più caratteri tilde per uscire solo da una delle sessioni SSH nella catena, ma conservare le altre. Ad esempio, se sei nidificato in 3 livelli (ad es. Ssh da local-> Machine1-> Machine2-> Machine3), Enter~.tornerai alla sessione locale, Enter~~.ti lascerà in Machine1 e Enter~~~.ti lascerà in Machine2 . Funziona anche con altre sequenze di escape, come spostare temporaneamente la sessione ssh in background. Quanto sopra funziona per qualsiasi livello di nidificazione, semplicemente aggiungendo più tilde.

Infine, è possibile utilizzare Enter~?per stampare un menu di aiuto dei comandi di escape disponibili.

TL; DR: i comandi di escape supportati sono sequenze di escape supportate:

 ~.   - 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.)

11
+1 per conoscere la password di prova segreta dodecatouple per sparare a sshd in testa. L'hai scoperto allo stesso modo in cui l'ho fatto (digitando male ~/.somethingorotherdopo aver premuto Invio)?
voretaq7,

2
@ voretaq7: No, non ero così intelligente, ma quando qualcuno mi ha fatto capire che sono andato "Davvero? Quindi è quello che stava succedendo tutte le volte che la mia shell è diventata BANG! senza motivo quando stavo scrivendo?" . Non è una sequenza comune tranne nei mistypes di quello che hai citato, ma può succedere.
Caleb,

14
Per cui "segreto" significa "nella pagina man".
Larks

4
Mentre molte persone non lo sanno, è davvero un segreto in bella vista. man sshtratta questo nella ESCAPE CHARACTERSsezione. ~.(Disconnect) e ~^Z(background ssh) sono molto utili.
Stefan Lasiewski,

9
Ovviamente è nella pagina man :) Ho usato la parola segreta solo perché l'OP ha fatto, e stavo usando la lingua nella guancia. Il problema con questa funzione è che le persone non sanno dove cercarlo, si aspettano che i personaggi di controllo e tali segnali facciano parte della shell o simili. Una volta che sai dove cercare o anche cosa chiedere, ovviamente è lì.
Caleb,

12

SSH offre una struttura keep-alive. Aggiungi quanto segue al tuo locale ~/.ssh/config(crea se non esiste):

ServerAliveInterval 15
ServerAliveCount 3

Questa impostazione stabilirà un segnale keep-alive inviato ogni 15 secondi attraverso il tunnel sicuro. Dopo tre errori consecutivi, il client SSH verrà chiuso.

Nota che su alcuni sistemi (incluso macOS 10.14) invece deve essere:

ServerAliveInterval 15
ServerAliveCountMax 3

Tratto da questa risposta su ask.ubuntu: https://askubuntu.com/a/29967/30266


9

Il fatto che si blocchi è una funzione di TCP, non di SSH. L'applicazione non ha modo di sapere che la sessione / connessione TCP è stata interrotta a meno che TCP non informi l'applicazione utilizzando la connessione che la connessione non esiste più. Dal punto di vista di ciascun host, la sessione TCP è ancora nello stato Stabilito e non c'è nulla da dire che una sessione inattiva lunga (nessun flusso di dati) non è valida se non un RST o una mancanza di risposta a un pacchetto keepalive TCP (che non è implementato universalmente). Questo non sembra essere un bug in SSH per me, mi aspetto questo comportamento.


5

Se la connessione è correttamente bloccata, qualsiasi combinazione di tasti magica non passerà poiché la connessione è già bloccata prima di premere i tasti. Puoi dire al client di terminare, ma ciò non influirà sulla cronologia conservata (o meno) alla fine del server.

Sebbene questo non risponda effettivamente alla domanda, può aiutare a ridurre gli effetti di un blocco della connessione: quando lavoro in remoto (e anche di solito quando non lo sono) corro screen(con o senza il byobuwrapper a seconda della sua disponibilità) così che se c'è qualche tipo di connessione, la mia sessione, con tutta la sua cronologia, viene mantenuta e disponibile nello stato in cui l'ho lasciata quando mi riconnetto.


6
Il tuo suggerimento sullo schermo va bene, ma il primo bit non è in realtà applicabile al problema. Non hai bisogno di ottenere le chiavi dal lato remoto, devi solo farle passare al client ssh LOCALE! L'OP vuole che il suo guscio locale sia indietro, compresa la storia. SSH prende il controllo e non risponde alle normali sequenze di interruzioni come CTRL-C perché le trasmette. C'è un modo per superare e terminare il client locale, vedi la mia risposta. La cronologia sull'estremità locale viene in genere mantenuta comunque se si accede nuovamente, a seconda della configurazione della shell.
Caleb,

2
@Caleb: la domanda menzionava specificamente la perdita di cronologia e la cronologia dei comandi è memorizzata sul lato server. Per dire al server di fare qualcosa di diverso con la cronologia, devi inviare un messaggio al server per dirgli di fare qualcosa di diverso con la cronologia. Naturalmente ci sono modi per fare in modo che bash (e alcune altre shell) registrino immediatamente le righe della cronologia piuttosto che raccoglierle nella RAM finché l'utente non esiste correttamente la shell con exit/ logoutche risolverebbe il problema della cronologia senza usare screen.
David Spillett,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.