A chave de escape SSH ("~") só funciona quando a conexão está travada?

A chave de escape SSH ("~") só funciona quando a conexão está travada?

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 bashna máquina remota, a chave de escape SSH funciona! Quando corro ashpara bashdentro 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 catcomando e insira a sequência de escape.

O catcomando 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-catrás catda casca.

Exemplo Se necessário, abra um prompt e execute catdigitando cate 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_terminalserá chamada. O que ask_terminalfaz? 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, ashimprime <ESC>[6ne sshdpassa de volta sshpara o emulador de terminal. Imediatamente, antes que você possa pressionar ~, seu emulador de terminal envia algo como <ESC>[47;13Ra entrada padrão e sshpassa pela conexão de sshde para ash, informando ashonde 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~Ce, 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).

informação relacionada