6

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

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

~C: command not found

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

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

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

Но это очень странно. Экранирующий ключ должен быть перехвачен клиентом SSH и даже не перенаправлен в удаленную оболочку. Так почему же важно, какая именно удаленная оболочка получает данные от SSH?

3 ответа3

3

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

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

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

$ 
$ 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 - это команда "Query Cursor Position" - она говорит эмулятору терминала отправить обратно другой управляющий код ANSI, который сообщает оболочке, где находится курсор (точка вставки текста) в окне терминала.

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

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

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

1

Вы спросили Конечно, SSH-клиент escape-ключ не должен работать, как это ??

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

Если вы нажмете Enter, то ~ и в приглашении не появится символ ~ что escape будет действовать в ssh .

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

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

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

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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .