SSH/Expect脚本疑问:expect匹配异常与重复logout输出问题
关于Expect实现SSH登录的输出异常问题解答
问题场景
尝试用Expect实现SSH远程登录,脚本可运行但输出不符合预期,具体信息如下:
所用Shell脚本
#!/bin/sh expect -c ' spawn ssh USER@ADDRESS ; expect "?assword:" ; send "MyPassword\r" ; expect "?" ; send "logout\r" ; interact'
MacOS终端输出
ip87-114:Downloads tasiyuchien$ ./test.sh spawn ssh USER@ADDRESS Password: logout Last login: Tue Sep 13 18:17:21 2022 from ADDRESS xdn42o221:~ USER$ logout Connection to ADDRESS closed. ip87-114:Downloads tasiyuchien$
疑问1解答
首先明确:Expect默认采用glob匹配规则,而非正则表达式,所以?和*的行为和正则中的对应符号不同:
- 你看到
Password:后直接输出logout,是因为glob模式下?匹配任意单个字符(包括换行、空格这类不可见字符)。输入密码回车后,SSH终端会输出一个换行符(Password:后的空行),这个单个字符刚好被expect "?"命中,脚本立刻执行send "logout\r",因此还没等到远程主机的提示符就发送了登出命令。 - 换成
*后登出失败,是因为glob模式下*匹配任意长度的字符序列(包括空),但expect "*"会等待输入缓冲区出现有效匹配内容。发送密码后,远程主机需要时间返回登录信息和提示符,此时缓冲区暂时没有能触发匹配的完整内容,导致脚本卡在expect "*"步骤,无法执行后续的send "logout\r"。
正确的做法是匹配远程主机的具体提示符,比如你的远程提示符是USER$,可改为expect "USER\$"(特殊字符$需要转义),或用正则模式expect -re ".*\$"匹配提示符结尾的$。
疑问2解答
两个logout的来源完全不同:
- 第一个
logout是脚本中send "logout\r"的命令回显——Expect默认会把send的内容输出到终端,所以会显示这一行。 - 第二个
logout是远程主机执行logout命令后,终端输出的命令记录(即远程提示符后跟着的logout),之后远程主机断开连接,输出Connection to ADDRESS closed.。
这和expect continue无关,只是两次输出的场景不同而已。
内容的提问来源于stack exchange,提问作者b06901089
相关产品推荐
相关产品推荐

