使用tcl/expect搭建端口隧道遇输入回显异常的技术咨询
多余回显的产生原因
- 问题核心是多层终端行规程的状态错位,差异点全部来自expect创建的PTY(伪终端)层:
- expect启动spawn子进程时,会为子进程创建一套独立的PTY,用来模拟真实终端的行处理逻辑,这套逻辑默认包含输入自动回显、行缓冲、特殊字符转义等功能。
- 当你直接手动运行expect脚本时,PTY的上游是你实际操作的交互式终端,脚本里写的
stty raw -echo会正确作用在这套PTY上,关闭自动回显、行缓冲等处理,输入输出直接透传,不会出现回显问题。 - 但当socat把expect的标准输入输出接到
tcp-l:200的监听端口时,这套PTY的上游不再是交互式终端,PTY创建时加载的默认termios参数是开启ECHO功能的:从TCP通道收到的每一个输入字节,PTY会默认拷贝一份回显到输出通道,顺着socat的连接回传给terminal3里的nc,就出现了“输入内容自动回显给自身”的现象。
- 为什么socat直接连接
nc localhost 2000没有这个问题?因为直连模式下不存在PTY层,是纯TCP字节流转发,根本没有终端行规程的自动回显逻辑,自然不会产生多余回显。 - 当前脚本的配置缺陷:虽然写了
stty raw -echo,但没有显式强制关闭PTY的ECHO标志,且interact的默认逻辑没有覆盖非终端上游场景下的回显行为,最终触发了PTY默认参数的回显逻辑。
多级跳板搭建MongoDB隧道的方案可行性
- 整体方案完全可行,你遇到的回显问题只是PTY参数配置错位的小问题,不是架构本身的缺陷。
- 关于你最顾虑的“流的原始性保持”:
- 只要正确配置expect层的PTY参数,关闭所有行规程处理(包括ECHO、ICANON、特殊字符转义),expect完全可以实现无内容篡改的双向字节透传。MongoDB基于TCP的二进制协议,只要透传层不做行缓冲、字符转换,就可以完整兼容,不会出现协议解析错误。
- expect的纯透传模式(不做正则匹配、不做内容替换)本身不会解析、修改流量payload,是纯字节搬运的逻辑,对二进制协议的兼容性是有保障的。
- 你现在遇到的回显问题,本质是多余的PTY回显字节被塞进了透传流里,只要把这个多余的处理关掉,透传的流就是完全原始的TCP payload,不存在流被破坏的问题。
内容的提问来源于stack exchange,提问作者NiMa Thr
相关产品推荐
相关产品推荐

