Ser*_*nyy 0 command-line escape-characters
假设我打开了两个 shell,一个 PID 为 1234,另一个为 5678。
我可以清除屏幕并重置另一个外壳,echo $'\033c' > /proc/1234/fd/0
就像reset
在终端本身的提示上输入一样。但是,当我echo $'\04' > /proc/1234/fd/0
发送 EOT 字符时,这似乎不起作用。我怎样才能达到预期的效果?
首先,一个 tty,即使它看起来是一个单一的文件对象,实际上也是一对管道/队列——一个用于输出,一个用于输入,每个的另一端连接到某些硬件设备,或者在伪 tty 的情况下可用于另一个程序。当您向链接到 tty 的 fd 写入任何内容时,您正在写入输出队列,即使这是您进程的 fd 0 (stdin),并且不会循环回输入队列。
在大多数 Unix 系统上(OpenBSD除外),有一个特殊的 ioctl ( TIOCSTI
) 允许您将一个字节插入到 tty 的输入队列中,就好像它是从另一端接收到的一样。TIOCSTI
仅当不在调用它的进程的控制 tty 上使用时才以 root 身份工作。
$ cc -Wall tiocsti.c -o tiocsti
Run Code Online (Sandbox Code Playgroud)
-- 作为根 --
# printf '\04' | ./tiocsti >/proc/5460/fd/0
Run Code Online (Sandbox Code Playgroud)
如果您的进程在伪 tty 中运行,另一种“伪造”输入的方法是将调试器连接到持有伪 tty 主端的进程,并将write(2)
您的东西从那里放入其中。
$ gdb -p pid_of_xterm
(gdb) p write(4, "\x04", 1) # 4 is the fd of the master pty
(gdb) c
Run Code Online (Sandbox Code Playgroud)
这两种方法都太过分了。如果你想控制一个正在运行的进程,你最好将调试器附加到那个进程上,而不是伪造一些输入;如果你想工具化一个交互式程序,你最好在expect
; 两者都可以在任何 Unix 系统上运行,并且不需要额外的权限。
还要注意,^D
/\004
只会EOF
在a) tty 处于规范模式下工作b )c_cc[VEOF]
特殊字符没有更改为其他内容c ) 输出队列为空时(否则c_cc[VEOF]
必须发送两次)。当然,只是从 tty 读取的进程将获得 EOF 或那些字节,不一定是 shell。
tiocstic.c
$ cc -Wall tiocsti.c -o tiocsti
Run Code Online (Sandbox Code Playgroud)