再次使用 socat 和 rich terminal

再次使用 socat 和 rich terminal

socat在终端上执行socat - UNIX-listen:/tmp/sock

然后我转到另一个终端并启动一个程序(通过 python),使其似乎在第一个终端中运行,这是一个例子:

s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
s.connect("/tmp/sock")
proc=subprocess.Popen(['prg'], stdin=s, stdout=s, stderr=s, shell=False)
proc.wait()

例如,具有简单输入/输出的程序(如“cat”)运行良好,但更复杂的程序(如“vim”或“bash”)显然不太令人满意。除此之外,当我点击Cntrl-C第一个终端时,它socat被终止,而我更希望将键盘中断传递给程序prg(在上面的 python 代码中启动)。

我的问题是:如果可能的话,如何告诉它socat表现得像prg终端所有者而不是socat它自己。

PS. 这个问题可能与这个,但事实并非如此,因为在那个问题中prg被 直接调用socat,所以可以使用EXEC选项。

答案1

信号和 tty 所有权不能“神奇地”通过套接字传输。

通过 AF_UNIX,你可以发送 tty 文件描述符本身(使用发送消息和 recvmsg),并让接收方使用它(和不是将套接字作为子进程的 stdout/stderr。这不能用普通的 socat 来完成,但是这种方法被 tmux 工具等内部使用。


使用普通的 socat,您最多可以让它在按下 Ctrl+C 时发送一个文字 0x03 字节 (^C)(这是 telnet 和 ssh 所做的)。您可以通过按Ctrl+VCtrl+C一次发送来测试这一点,或者在 socat 之前运行stty raw以永久进入“原始模式”。

这还不足以让接收端真正理解不过,按键。最基本的方法是手动检查每个字节 - 当它看到 0x03 时发送 SIGINT;否则将其写入子进程的标准输入。

但是,telnetd 和 sshd 所做的是在套接字和子进程之间添加“伪 tty”——在 Python 中,您可以使用创建一个os.openpty();“从属”端需要作为子进程的 stdout/stderr,并且您的脚本需要在循环中运行,在套接字和“主”端之间复制数据。

这仍然不是相当足够 – 功能齐全的终端登录协议(例如 SSH 或 Telnet)也会有消息来更新 pty 的尺寸,并对 termios 设置更改做出反应(例如“本地回显”设置和 中看到的其他设置stty)。

阅读 telnet 客户端和 telnetd 服务器的源代码(例如来自 GNU inetutils)会很有用,因为它们正是这样做的。

相关内容