Dak*_*ron 0 shell bash expect stdout stdin
在构建一个小的 Expect 脚本时,我注意到,执行脚本后,一些字符会自动出现在 bash 的输入中。我以前在其他程序上见过这种情况,但在这里我有一些可重现的东西。
我的期望脚本如下:
#!/usr/bin/expect
spawn ssh root@[lindex $argv 0]
expect "password:"
send "[lindex $argv 1]\r"
expect "~#"
Run Code Online (Sandbox Code Playgroud)
这是结果:
user@PC:~$ expect test.exp 192.168.0.2 root
spawn ssh root@192.168.0.2
root@192.168.0.2's password:
^[[51;117Rroot@device:~# user@PC:~$ ;117R
-bash: syntax error near unexpected token `;'
user@PC:~$
Run Code Online (Sandbox Code Playgroud)
正如您在输出的第五行中看到的那样,stdout ( ^[[51;117R) 上有一些随机字符,其中一些泄漏到 shell 输入行 ( ;117R) 上。如果我在执行 Expect 脚本后按 Enter 键,bash 会尝试解释该 ( ;117R),就像我已将其输入到 bash 中一样。
我的问题是,这里发生了什么以及如何阻止它?
这些不是“随机字符”。
% printf '\e[51;117R' | 控制台解码 ECMA48 心肺复苏术 51;117 %
在远程系统的登录过程中运行的操作是,通过向其终端发送设备状态报告控制序列,从该终端请求光标位置报告。终端(您的终端,几跳之外,通过ssh和传递了 DSR 输出expect)正在按时生成并发送它。
% printf '\x1b[6n' ; 控制台解码 ECMA48 ^[[30;1R 心肺复苏 30;1 如果 %
此类报告从终端到达主机(即直接连接到终端的机器),其方式与键入输入完全相同。在主机上运行的程序没有可靠的方法来知道您不是简单地键入了光标位置报告。当然,expect此时并没有在终端输入上读取和发送,因此 CPR 已排队等待下一个从终端读取输入的程序读取,该程序是expect完成后的 shell。您所看到的是您的 shell 对此类输入控制序列的反应。
这些是终端输入处理实际上应该始终是具有适当状态机的适当 ECMA-48 解码器的原因之一。你的 shell 的行编辑系统不是。(ZLE、Readline 或 libedit 都没有真正正确处理终端输入控制序列。)它使用模式匹配来解码内容,这并不能做正确的事情。请注意它如何仅忽略控制序列的前四个字符。适当的 ECMA-48 输入解码器将解码整个控制序列,包括所有参数字符直到最终字符,将其识别为 CPR,并(希望)将其作为无用的输入丢弃。
至于首先请求 CPR 的是什么:为此,您必须检查远程系统,以及它在终端登录时运行的程序。罪魁祸首可能是 Xtermresize程序。(请注意,当 Xterm 不是您的终端时,您不应该使用该程序,因为它会将TERM环境变量错误地设置为某种xterm类型。)但这resize并不是唯一的可能性。
console-decode-ecma48“。 小吃指南。软件。TERM“。 小吃指南。软件。