You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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的来源完全不同:

  1. 第一个logout是脚本中send "logout\r"的命令回显——Expect默认会把send的内容输出到终端,所以会显示这一行。
  2. 第二个logout是远程主机执行logout命令后,终端输出的命令记录(即远程提示符后跟着的logout),之后远程主机断开连接,输出Connection to ADDRESS closed.。

这和expect continue无关,只是两次输出的场景不同而已。


内容的提问来源于stack exchange,提问作者b06901089

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 20:10:43