我试图弄清楚当我在 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。发生的情况是这样的:
终端仿真器生成
^C
.有一个 tty 线路规则可能会或可能不会拦截该字节并将其“转换”为信号。
如果线路规则配置为触发 SIGINT,
^C
那么它将向当前前台进程组发送 SIGINT。ssh
位于前台进程组中,将收到信号并退出。如果线路规则配置为不进行
^C
特殊处理,那么它将^C
像任何“正常”字节一样发送(例如像a
或5
),ssh
将读取它并将其发送到远程端。进而…
在远程端可能有也可能没有分配 tty。
如果没有 tty,则 SSH 服务器启动的程序将
^C
在其标准输入上接收。如果存在 tty,则存在线路规则,该线路规则可能会也可能不会配置为进行
^C
特殊处理。与本地发生的情况类似,远程线路规则将向(远程)前台进程组发送 SIGINT 或^C
像任何“正常”字节一样传递。
ssh
启动为ssh … some_command
或ssh -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。