当我有一个无响应的 SSH 连接时,我可以使用 终止它<enter>~.
。但是,当连接有响应时,转义~
不起作用。它只是在控制台上打印一个波浪线。
因此,如果我想修改 SSH 端口转发并按下<enter>~C<enter>
,我得到的只是:
~C: command not found
(来自bash
,而不是来自ssh
。)
我需要做什么才能使 SSH 退出密钥正常工作?
编辑:我找到了一个重要线索:远程 shell 实际上是ash
,而不是bash
。当我bash
在远程机器上运行时,SSH 退出键有效!当我ash
在bash
inside中运行 时ash
,它再次不起作用!
但这很奇怪。退出键应该被 SSH 客户端捕获,甚至不应该转发到远程 shell。那么,究竟哪个远程 shell 正在接收来自 SSH 的输入有什么关系呢?
答案1
简单的解决方法:运行cat
命令,然后输入转义序列。
该cat
命令默认会打印传入的内容stdin
,因此运行时不会发送转义字符,您可以照常使用 ssh 转义键。完成后,只需ctrl-c
返回cat
shell 即可。
例子
如果需要,打开提示并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-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 转义码,该转义码告诉 shell 光标(文本插入点)在终端窗口中的位置。
因此,只要您按下Enter
,ash
就会打印出<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(等待连接终止时)
~? - 此消息
~~ - 通过输入两次转义字符来发送转义字符
(请注意,转义字符仅在换行符后立即被识别。)