%20s%C3%B3%20funciona%20quando%20a%20conex%C3%A3o%20est%C3%A1%20travada%3F.png)
Quando tenho uma conexão SSH que não responde, posso eliminá-la com <enter>~.
. Porém, quando a conexão está respondendo, o ~
escape não funciona. Apenas imprime um tilda no console.
Então, se eu quiser modificar o encaminhamento de porta SSH e pressionar <enter>~C<enter>
, tudo que recebo é:
~C: command not found
(De bash
, não de ssh
.)
O que preciso fazer para que a chave de escape SSH funcione corretamente?
EDITAR:Encontrei uma grande pista: na verdade, o shell remoto era ash
, não bash
. Quando executo bash
na máquina remota, a chave de escape SSH funciona! Quando corro ash
para bash
dentro ash
, de novo, não funciona!
Mas isso é muito estranho. A chave de escape deve ser capturada pelo cliente SSH e nem mesmo encaminhada para o shell remoto. Então, por que deveria importar exatamente qual shell remoto está recebendo entrada do SSH?
Responder1
Solução simples: execute o cat
comando e insira a sequência de escape.
O cat
comando imprimirá por padrão o que é passado stdin
, portanto, enquanto estiver em execução, nenhum caractere de escape será enviado e você poderá usar a chave de escape ssh normalmente. Quando feito logo ctrl-c
atrás cat
da casca.
Exemplo
Se necessário, abra um prompt e execute cat
digitando cat
e pressionando enter.
$
$ cat
Agora digite ~?
~?
Supported escape sequences:
~. - 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
Funciona! Agora basta digitar qualquer comando. Então, para retornar ao prompt, pressione control-C.
^C
$
Responder2
Eu descobri o segredo!
Como postei na "edição" acima, o shell remoto era BusyBox ash
, não bash
.
De libbb/lineedit.c:2336-2338
, nas fontes do BusyBox:
/* Print out the command prompt, optionally ask where cursor is */
parse_and_put_prompt(prompt);
ask_terminal();
Isso é usado para imprimir o prompt de comando no formato ash
. Mas observe, assim que o prompt for impresso, outra função chamada ask_terminal
será chamada. O que ask_terminal
faz? Ele imprime os seguintes caracteres: <ESCAPE>[6n
.
Você nunca vê esses caracteres em seu terminal. Na verdade, eles são um código de escape de controle de terminal ANSI. <ESC>[6n
é um comando "Query Cursor Position" - ele diz ao emulador de terminal para enviar de volta outro código de escape ANSI, que informa ao shell onde o cursor (ponto de inserção de texto) está localizado na janela do terminal.
Assim que você pressiona Enter
, ash
imprime <ESC>[6n
e sshd
passa de volta ssh
para o emulador de terminal. Imediatamente, antes que você possa pressionar ~
, seu emulador de terminal envia algo como <ESC>[47;13R
a entrada padrão e ssh
passa pela conexão de sshd
e para ash
, informando ash
onde está o cursor.
Agora, o cliente SSH não sabe realmente o que significam esses códigos de escape ANSI. Para SSH, todos eles são apenas caracteres lidos da entrada padrão. Em vez de ver <ENTER>~C
, o cliente SSH vê <ENTER><ESC>[47;13R~C
e, como não vê o ~
logo depois Enter
, não pensa que seja um código de escape.
A questão é o que fazer sobre isso. Seria bom se o OpenSSH entendesse os escapes ANSI enviados pelo terminal e ainda aceitasse o ~
caractere de escape após um comando de controle do terminal ANSI. Posso enviar um patch ao pessoal do OpenSSH e ver se eles estão interessados em consertar isso ...
Responder3
Você perguntouCertamente, a chave de escape do cliente SSH não deveria funcionar assim?
Sim, deve funcionar assim:
Se você pressionar Enterthen ~e não aparecer o caractere ~
no prompt que o escape atuará no ssh
.
Se você pressionar novamente, ~ele aparecerá no seu prompt e atuará no shell de trabalho (o bash no seu exemplo), que tentaráexpandire use como sabe.
Observe que para funcionar você ~
tem que ser o primeiro de seubuffer de linha, então se você inserir algum caractere e depois de apagar toda a linha não existir maisnovoe você precisa pressionar Enternovamente.
Quando pressiono ~?
obtenho
Sequências de escape suportadas:
~. - encerrar a conexão (e quaisquer sessões multiplexadas)
~B - enviar um BREAK para o sistema remoto
~C - abrir uma linha de comando
~R - Solicitar rechave (apenas protocolo SSH 2)
~^Z - suspender ssh
~# - listar conexões encaminhadas
~ & - ssh em segundo plano (ao aguardar o término das conexões)
~? - esta mensagem
~~ - envie o caractere de escape digitando-o duas vezes
(observe que os escapes só são reconhecidos imediatamente após a nova linha).