经常使用跳板机维护远程服务的同学可能会有这么一个苦恼,就是每次连接都需要一连串交互式操作才能连上目标机器,遇到电脑息屏或者退出终端还得再来一遍
比如维护和查询数据库,可能就需要以下操作:
- ssh 到远程机器
- 输入令牌
- 输入密码
- 查看机器列表
- 选择特定机器
- 连接特定数据库客户端
- 输入用户名
- 输入密码
- 选择对应数据库
完成以上 9 个步骤,我们才可以真正开始操作数据库。这个过程如果每天重复多次,实在让人头疼,而 expect 可以帮我们把这些步骤一键搞定
Expect 是什么
Expect 本质上是一个自动化交互工具,最经典的用法就是:
启动一个程序 → 等待程序输出特定内容 → 自动输入 → 再等待 → 再输入。
比如我们手工 ssh 登录一台机器,过程是这样的:
1 | $ ssh root@192.168.1.100 # 发起连接 |
用 Expect 可以把这个过程完全自动化:
1 | #!/usr/bin/expect |
四个核心概念
spawn:启动程序
1 | spawn ssh root@192.168.1.100 |
相当于在终端执行 ssh root@192.168.1.100,但 Expect 会接管这个进程的输入输出:
1 | Expect |
expect:等待特定输出
1 | expect "password:" |
Expect 会持续读取程序输出,直到匹配到 password: 才继续执行下一条命令。比如 ssh 输出了:
1 | Connecting to 192.168.1.100... |
匹配到 password: 后,流程才往下走。
send:发送输入
1 | send "123456\r" |
向程序发送 123456 并回车(\r 相当于按下 Enter)。
interact:交回人工控制
1 | interact |
自动操作完成后,把终端交还给用户,你可以继续手动操作。
串起来看
1 | spawn ssh root@192.168.1.100 |
整个执行流程:启动 ssh → 等待 password: → 自动输入密码 → 进入服务器 → 交还给用户。这就是最经典的 Expect 用法。
示例
还记得开头提到的数据库连接场景吗?9 个步骤手动操作一遍要好几分钟,用 Expect 写成脚本后,一条命令直接搞定:
1 | #!/usr/bin/expect |
保存为 connect_db.sh,加上执行权限后直接运行即可:
1 | chmod +x connect_db.sh |
脚本会自动完成前面的 9 个步骤,最后通过 interact 把终端交还给你,直接进入数据库开始操作。
说明
示例的第 2 步需要用户手动输入令牌。如果本地安装了 TOTP 令牌生成工具(如 oathtool),也可以在脚本中直接调用来生成,实现完全自动化。