SSH 退出键(“~”)仅在连接卡住时才有效?

SSH 退出键(“~”)仅在连接卡住时才有效?

当我有一个无响应的 SSH 连接时,我可以使用 终止它<enter>~.。但是,当连接有响应时,转义~不起作用。它只是在控制台上打印一个波浪线。

因此,如果我想修改 SSH 端口转发并按下<enter>~C<enter>,我得到的只是:

~C: command not found

(来自bash,而不是来自ssh。)

我需要做什么才能使 SSH 退出密钥正常工作?

编辑:我找到了一个重要线索:远程 shell 实际上是ash,而不是bash。当我bash在远程机器上运行时,SSH 退出键有效!当我ashbashinside中运行 时ash,它再次不起作用!

但这很奇怪。退出键应该被 SSH 客户端捕获,甚至不应该转发到远程 shell。那么,究竟哪个远程 shell 正在接收来自 SSH 的输入有什么关系呢?

答案1

简单的解决方法:运行cat命令,然后输入转义序列。

cat命令默认会打印传入的内容stdin,因此运行时不会发送转义字符,您可以照常使用 ssh 转义键。完成后,只需ctrl-c返回catshell 即可。

例子 如果需要,打开提示并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

我已经知道这个秘密了!

正如我在上面的“编辑”中所说,远程 shell 是 BusyBox ash,而不是bash

来自libbb/lineedit.c:2336-2338BusyBox 来源:

/* 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 转义码,该转义码告诉 shell 光标(文本插入点)在终端窗口中的位置。

因此,只要您按下Enterash就会打印出<ESC>[6n,并将sshd其传递回ssh终端仿真器并从那里传递回终端仿真器。在您按下 之前~,您的终端仿真器会立即将类似<ESC>[47;13R标准输入的内容发送到 ,并ssh通过连接将其传递到sshd并从那里传递到ash,告诉ash您的光标在哪里。

现在,SSH 客户端实际上并不知道这些 ANSI 转义码的含义。对于 SSH 来说,它们都只是从标准输入读取的字符。SSH<ENTER>~C客户端看到的不是<ENTER><ESC>[47;13R~C,而是 ,而且由于它看不到~后面的Enter,所以它不认为这是转义码。

问题是该怎么做。如果 OpenSSH 能够理解终端发送的那些 ANSI 转义字符,并且仍然接受~ANSI 终端控制命令后的转义字符,那就太好了。我可能会向 OpenSSH 人员发送一个补丁,看看他们是否有兴趣修复这个问题……

答案3

你问当然,SSH 客户端退出键不应该这样工作吗?

是的,它应该可以工作,所以:

如果你按下Enter然后~它不会出现~提示中的字符,退出将在提示中起作用ssh

如果你再次按下,~它将出现在你的提示上,并将在工作 shell 上起作用(你示例中的 bash),它将尝试扩张并按照其所知的方式使用。

请注意,要工作,~必须是你的第一个行缓冲区,所以如果你输入任何字符,然后你删除所有行,那么就不再是新的您需要再按Enter一次。

当我按下时~?我得到

支持的转义序列:
~. - 终止连接(以及任何多路复用会话)
~B - 向远程系统发送 BREAK
~C - 打开命令行
~R - 请求重新密钥(仅限 SSH 协议 2)
~^Z - 暂停 ssh
~# - 列出转发的连接
~& - 后台 ssh(等待连接终止时)
~? - 此消息
~~ - 通过输入两次转义字符来发送转义字符
(请注意,转义字符仅在换行符后立即被识别。)

相关内容