expect转义符及远程主机执行命令

时间:2021-12-27 14:22:10

expect介绍

expect-send对:expect等待输出并判定特定的字符,通常是提示符,当字符匹配,则send下一步的操作;若字符与expect期望的输出不一只时,往往会报错退出。
expect不支持太复杂的命令,一般都是按照既定的返回执行下一步的操作,比较呆板,但很多时候还是很有用的

expect的转义符/逃逸符

在命令send时,往往有写特殊字符需要进行转义:

1.” 对应转义字符: \\\”
2.[ 对应转义字符: [
3.} 对应转义字符: }
4.$ 对应转义字符: \\\$
5.\ 对应转义字符: \\\
6.` 对应转义字符: \`

遇到的问题

最近由于有大批量的任务需要在不同的主机上进行执行,使用过程中,偶尔会出现expect: spawn id exp6 not open的报错,一直以为是超时的问题,但是set timeout -1 禁止超时后,仍然会出现报错

解决过程及方法

问题分析结果:
经过分析,发现是偶尔已一两台主机的命令行提示符不一致;不一致的原因在于命令提示符有的主机没有空格,大多数主机是默认有空格的。
问题解决:
expect支持if判断,但是对于根据expect的返回结果来进行判断,对于这种简单的交互过程是不现实的。所以最好是能够将命令提示符进行统一,即开始expect,统一设置PS1的格式,最后问题解决。

事例代码如下:

#!/usr/bin/expect
#这里ip可以设置成输入变量,便于批量执行
set ipaddr "localhost"
#设置登录的用户名和密码;需要有登录权限,并且在批量主机执行时,密码需要一致
set passwd "passwd"
spawn ssh root@$ipaddr
expect {
"yes/no" { send "yes\r"; exp_continue}
"password:" { send "$passwd\r" }
}
set timeout 3
#设置PS1的格式
send "export PS1=\\\"\[\\\u]\\\\$\\\"\r"
#期待接收到的返回
expect "*]#"
#创建一个文件验证已经登录成功
send "touch /tmp/test.txt\r"
send "exit\r"
expect eof
exit

总结:

若需要使用expect进行简单自动化的主机,有事并不能完全预测返回的结果,有一定的缺陷,但在自动化管理中还是很有用的,当然也需要考虑到不同的主机环境可能不一致的情况,这时需要做一个统一。或者使用if,while等条件语句进行进一步的优化