Клавиша выхода SSH («~») работает только при зависании соединения?

Клавиша выхода SSH («~») работает только при зависании соединения?

Когда у меня неотвечающее SSH-соединение, я могу убить его с помощью <enter>~.. Однако, когда соединение отвечает, ~выход не работает. Он просто печатает тильду в консоли.

Итак, если я захочу изменить переадресацию портов SSH и нажму <enter>~C<enter>, все, что я получу, это:

~C: command not found

(Из bash, а не из ssh.)

Что мне нужно сделать, чтобы клавиша выхода SSH работала правильно?

РЕДАКТИРОВАТЬ:Я нашел большую зацепку: удаленная оболочка на самом деле была ash, а не bash. Когда я запускаю bashна удаленной машине, клавиша SSH escape работает! Когда я запускаю ashвнутри , bashснова ash, она не работает!

Но это очень странно. Клавиша escape должна быть перехвачена SSH-клиентом и даже не перенаправлена ​​в удаленную оболочку. Так почему же должно быть важно, какая именно удаленная оболочка получает входные данные от SSH?

решение1

Простой обходной путь: выполните catкоманду, а затем введите escape-последовательность.

Команда catпо умолчанию выведет то, что передано stdin, поэтому во время ее выполнения не будет отправлено никаких экранирующих символов, и вы можете использовать клавишу ssh escape как обычно. После этого просто ctrl-cвернитесь catв оболочку.

Пример При необходимости откройте командную строку и выполните команду, catвведя ее catи нажав Enter.

$ 
$ cat 

Теперь введите ~?

~?
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

Работает! Теперь просто введите любую команду. Затем, чтобы вернуться к подсказке, нажмите control-C.

^C
$

решение2

Я разгадал секрет!

Как я уже писал в «редактировании» выше, удаленная оболочка была BusyBox ash, а не bash.

Из libbb/lineedit.c:2336-2338источников BusyBox:

/* Print out the command prompt, optionally ask where cursor is */
parse_and_put_prompt(prompt);
ask_terminal();

Это используется для печати командной строки в ash. Но обратите внимание, как только она печатает приглашение, вызывается другая функция ask_terminal. Что она ask_terminalделает? Она печатает следующие символы: <ESCAPE>[6n.

Вы никогда не увидите эти символы в своем терминале. На самом деле, это управляющий код ANSI терминала. <ESC>[6n— это команда «Запросить позицию курсора» — она сообщает эмулятору терминала о необходимости отправить обратно другой управляющий код ANSI, который сообщает оболочке, где в окне терминала находится курсор (точка вставки текста).

Итак, как только вы нажимаете Enter, ashпечатает <ESC>[6n, и sshdпередает это обратно sshв эмулятор терминала и оттуда в него. Сразу же, до того, как вы сможете нажать ~, ваш эмулятор терминала отправляет что-то вроде <ESC>[47;13Rна стандартный ввод и sshпередает это по соединению в sshdи оттуда в ash, сообщая, ashгде находится ваш курсор.

Теперь клиент SSH на самом деле не знает, что означают эти управляющие коды ANSI. Для SSH они все просто символы, считанные со стандартного ввода. Вместо того, чтобы видеть <ENTER>~C, клиент SSH видит <ENTER><ESC>[47;13R~C, и поскольку он не видит ~сразу после Enter, он не думает, что это управляющий код.

Вопрос в том, что с этим делать. Было бы неплохо, если бы OpenSSH понимал эти экранированные последовательности ANSI, отправленные терминалом, и по-прежнему принимал бы ~символ экранирования после команды управления терминалом ANSI. Я могу отправить ребятам из OpenSSH патч и посмотреть, заинтересованы ли они в исправлении этого...

решение3

Вы спрашивалиНеужели клавиша выхода SSH-клиента не должна работать таким образом?

Да, это должно работать так:

Если вы нажмете Enterтогда и на подсказке ~не появится символ, то действие Escape будет выполнено в .~ssh

Если вы нажмете еще раз, ~он появится в командной строке и будет действовать в рабочей оболочке (bash в вашем примере), которая попытаетсярасширятьи использовать по своему усмотрению.

Обратите внимание, что для работы ~необходимо быть первым из вашихбуфер строки, поэтому если вы введете любой символ и после этого сотрете всю строку, то ее больше не будетновыйи вам нужно нажать Enterеще раз.

Когда я нажимаю, ~?я получаю

Поддерживаемые escape-последовательности:
~. - завершить соединение (и любые мультиплексные сеансы)
~B - отправить BREAK на удаленную систему
~C - открыть командную строку
~R - запросить повторный ввод (только протокол SSH 2)
~^Z - приостановить ssh
~# - вывести список перенаправленных соединений
~& - фоновый ssh ​​(при ожидании завершения соединений)
~? - это сообщение
~~ - отправить escape-символ, введя его дважды
(обратите внимание, что escape-символы распознаются только сразу после новой строки.)

Связанный контент