使用Expect进行Telnet自动化:认证慢吗?

4

我正在使用Telnet向Mikrotik路由器发送命令。

telnet 192.168.100.100 -l admin
Password: pass1234
[admin@ZYMMA] > /interface pppoe-server remove [find user=aspeed13]
[admin@ZYMMA] > quit

它运行良好。

现在我想使用expect tcl脚本自动化它:

#!/usr/bin/expect --
spawn telnet 192.168.100.100
expect "Login:"
send "admin\r"
expect "Password:"
send "pass1234\r"
expect "\[admin@ZYMMA\] >"
send "/interface pppoe-server remove \[find user=aspeed13\]\r"
expect "\[admin@ZYMMA\] >"
send "quit\r"

它能够工作,但在身份验证后(第6行:send "pass1234\r"),当路由器CLI正在加载时,它会冻结大约10秒,并显示以下字符:^ [[? 6c ^ [[24; 3R然后脚本运行正常。

我的问题是为什么手动访问Telnet时加载速度很快,而通过expect脚本访问时需要太长时间?我在论坛中阅读有关Telnet自动化的内容,他们说Telnet很慢,但由于手动方式太快,为什么使用expect需要花费时间才能加载?


1
expecttcl,不是 bash - ninjalj
如果您将下一个 expect 行替换为 expect -re ">",它是否有效? - ninjalj
感谢ninjalj的纠正。 - Naim Zard
关于用 expect -re ">" 替换下一行的问题,我尝试了一下,但脚本停止了并且等待超时。还有其他建议吗? - Naim Zard
在你的脚本顶部添加 exp_internal 1 来查看 expect 如何进行匹配。 - glenn jackman
4个回答

3
您看到的是终端协商导致的反弹,这是因为您没有在一个“真正”的终端中运行(严格地说,你是在运行 expect 的魔法终端,但它的行为并不像正常的终端)。
最简单的解决方法是在生成 telnet 会话之前将终端设置为其他东西,例如:
#!/usr/bin/expect --
set env(TERM) dumb
spawn telnet 192.168.100.100
# Rest of your script goes here ...

或者,您可以尝试正确响应进入VT102模式的请求以及光标位置的报告(这感觉像是很多工作),或者重写代码,使其在interact内完成所有操作(该操作将连接另一端与您正在运行的真实终端)。但如果设置环境变量可以解决问题,为什么要去做那些额外的麻烦呢?

(注:我建议在此处将终端设置为dumb,但关键是您需要使用能够正常工作的最简单的终端。愚笨的终端是理想的,因为它们几乎是完全愚蠢的,这样就很容易假装成它们...)


1
我尝试了set env(TERM) dumb,但是没有成功,连接延迟仍然相同 :( - Naim Zard
您觉得使用SSH比Telnet更快,还是两者一样?例如,是否可能在不到3秒钟的时间内使用Telnet(或SSH)打开/发送命令/关闭连接? - Naim Zard
2
@Naim:根据我的经验,我猜应该差不多,足以没有理由运行不安全的程序。(我喜欢使用加密密钥进行身份验证,实际上这使得程序在我的情况下更快。) - Donal Fellows
谢谢@Donal:你关于安全问题的看法肯定是正确的。我强调低响应时间的原因是因为这个脚本将被一个php网页调用。我尝试了phpTelnet,但它需要几乎相同的时间(略微更长一些)。所以实际上,通过转向expect脚本,我只节省了几秒钟。我尝试了带有Net::Telnet类的perl脚本,我又节省了几秒钟,整个过程需要10秒钟。所以似乎没有可能在10秒的阈值以下通过脚本进行终端连接。你同意吗,还是我错了? - Naim Zard
1
使用ssh,您还可以将要执行的命令和参数作为ssh的参数传递。使用cryptokeys和sshagent或仅使用无密码的密钥可能更容易:只需执行ssh admin@192.168.100.100 /bin/bash -c "/interface pppoe-server remove [find user=aspeed13]"-假设远程shell是bash。(这样您就不必等待发送和响应之间的延迟了...) - Johannes Kuhn
这是“真正的”Telnet吗?我想这取决于你如何定义“真正的”。 - Thufir

2

我的回答可能有点晚了。这是“Telnet自动配置命令”...我遇到了这个问题,并在Mikrotik Wiki上找到了解决方案:

在登录名后面添加+t。这个开关会自动检测关闭。

例如:发送“admin+t\r”

它工作得很好,不需要使用expect登录后等待约10秒。

这里有一个链接到Mikrotik WiKi帮助页面,其中包含更多的“开关”: http://wiki.mikrotik.com/wiki/Manual:Console_login_process#FAQ

P.S.:对我的英语表示抱歉。


1

你尝试过使用启用了 telnet 模拟的 netcat 吗?


1
你认为netcat比expect更有用吗?我会去了解一下,但如果你能提供一个小样例给我就太感谢了。 - Naim Zard
据我理解,expect和interact是可行的方法。我不知道netcat是否具有脚本编写能力。 - Thufir

1
有点晚了,但如果你想要使用expect加速字符输入,可以尝试使用"autoexpect"命令生成脚本,它会将交互保存在名为"script.exp"的文件中,该文件位于运行该命令的同一目录下。
例如: cd $HOME autoexpect telnet 192.168.100.100 # 其他telnet命令 exit
以上所有命令都将保存在~/script.exp中。 至于Tcl,我不知道这个脚本是否可以通过tcl运行。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接