Ctrl+c 或 Ctrl+z 如何通过 SSH 发送?

Ctrl+c 或 Ctrl+z 如何通过 SSH 发送?

我试图弄清楚当我在 PuTTY 或 OpenSSH 中按Ctrl+时到底发送到 SSH 主机的内容是什么。c我想做的就是以编程方式发送控制代码,这相当于用户按下Ctrl+时的z情况。到目前为止,每次我发送^C\cc\003它只是打印出来。必须有某种额外的信息让终端知道它被^C转义了?

我正在以编程方式将字符发送到已连接到 SSH 主机的 SSH 会话。我希望看到与打开 OpenSSH 客户端并按键盘上的Ctrl+时相同的效果。c

答案1

如果 Ctrl+c通过 SSH 发送,它是一个字节:^C即十六进制、八0x03进制003、ASCII ETX。
如果 Ctrl+z通过 SSH 发送,它是一个字节:^Z即十六进制、八0x1a进制032、ASCII SUB。

我写了“if”,因为客户端上的Ctrl+c可能会也可能不会生成到达服务器端的字节。在服务器端,这个字节可能会也可能不会到达 SSH 服务器启动的任何程序。

我不知道 Windows 中的 PuTTY 到底是如何处理这个问题的,但我知道 Linux 中的机制(即 Linux 客户端 + Linux 服务器)。我的回答汇总了其他几个答案的信息:

假设您ssh使用终端模拟器运行,然后按Ctrl+ c。发生的情况是这样的:

  1. 终端仿真器生成^C.

  2. 有一个 tty 线路规则可能会或可能不会拦截该字节并将其“转换”为信号。

    • 如果线路规则配置为触发 SIGINT,^C那么它将向当前前台进程组发送 SIGINT。ssh位于前台进程组中,将收到信号并退出。

    • 如果线路规则配置为不进行^C特殊处理,那么它将^C像任何“正常”字节一样发送(例如像a5),ssh将读取它并将其发送到远程端。进而…

  3. 在远程端可能有也可能没有分配 tty。

    • 如果没有 tty,则 SSH 服务器启动的程序将^C在其标准输入上接收。

    • 如果存在 tty,则存在线路规则,该线路规则可能会也可能不会配置为进行^C特殊处理。与本地发生的情况类似,远程线路规则将向(远程)前台进程组发送 SIGINT 或^C像任何“正常”字节一样传递。

ssh启动为ssh … some_commandssh -T …不在远程端分配 tty,并且不会使本地终端停止^C特殊处理。实际上 local Ctrl+c将终止本地程序(即其ssh本身)​​。但是,如果您通过管道传递到绕过本地线路规则,ssh那么您将能够将任意数据(包括^C字节)传递到some_command;在远程端,不会有可能破坏数据的线路规则。

ssh无需命令或使用命令启动-t-tt在某些情况下需要)确实在远程端分配一个 tty 并使本地终端停止^C特殊处理。实际上,本地Ctrl+c不会终止本地程序(即本身ssh),但它将到达^C远程端,远程线路规则将在远程端处理它;所以本地Ctrl+c可能会终止远程程序。远程线路规则将无法判断^C它是否来自本地Ctrl+c或(例如)来自管道printf "\003"ssh;这是同一个字节。当在远程端分配 tty 时,您无法通过管道来可靠地发送/接收任意数据ssh;远程端的线路规则会破坏数据。您可以从我的这个问题中获得一些额外的见解:ssh具有单独的 stdin、stdout、stderr 和 tty

到目前为止,每次我发送^C\cc\003它只是打印出来。

可能性:

  • 远程端没有 tty,因此没有线路规则可以“转换”^C为 SIGINT;并且程序以您实际可以看到的形式“打印出来”(如cat -A)。

  • 或者远端有tty,但线路规则配置为不^C特殊对待;终端驱动程序异或程序“打印出来”(很容易配置终端驱动程序以回显(以脱字符号表示)它作为输入获得的内容:)stty ctlecho

  • 或者远端有tty并且线路规则配置为^C特殊对待;但是程序捕获了 SIGINT,而不是终止自身,“将其打印出来”。

答案2

像这样的东西:

(echo ping google.com; sleep 3; printf "\003"; ) |
  ssh -tt localhost

答案3

我试图弄清楚当我在 putty 或 open ssh 中按 CTRL-C 时到底发送到 SSH 主机的内容是什么。

我不知道。

我想做的就是实用地发送控制代码,这些代码相当于用户按下 CTRL-Z 时的情况。

要以编程方式发送 Ctrl+C,请将 SIGINT 发送到 ssh,例如:

killalll -s SIGINT ssh

相当于ctrl+C在您有权访问的所有 SSH 会话中按 。同样对于 Ctrl+Z 使用 SIGTSTP:

killall -s SIGTSTP ssh

将在所有 ssh 终端中按 Ctrl+Z...并发送到特定的 ssh 会话,获取其 ssh PID 并使用kill

kill -s SIGTSTP PID

将在属于该 PID 的 ssh 会话上发送 Ctrl+Z。

相关内容