expect安装和使用
? Expect是一个我们常在shell交互时常用到的工具,它主要由expect-send组成。Expect是等待输出内容中的特定字符。然后由send发送特定的相应。Expect的工作流程类似于:小明和小红说:hello,小红发现小明说的是hello,然后就回复小明hi。然后小明说:你好,我是小明。小红发现小明说的是”你好,我是XX“,就回复”你好,我是小红“。 本文主要内容: 1.安装expect??? 2 expect的一些基本命令选项?? 3 expect脚本 1.??安装expect 1.1 yum 安装 yum安装就比较简单了,直接运行yum install expect就可以了. yum install expect
? 1.2 源码安装 源码安装前我们需要安装unzip和gcc install unzip gcc -y ? 源码安装我们需要下载两个源码包。tcl源码包和expect源码包。? 下载tcl源码包 cd /tmp &&wget http://core.tcl.tk/tcl/zip/release/tcl.zip
? 下载expect源码包 wget https:jaist.dl.sourceforge.net/project/expect/Expect/5.45.3/expect5.45.3.tar.gz
我们需要先编译安装tcl,因为expect包依赖于tcl。 解压压缩包并编译安装tcl unzip tcl.zip && cd ./tcl/unix
./configure && make && make install
解压压缩包并编译安装expect. cd /tmp && tar -xzvf expect5.45.3.tar.gz && cd expect5.45.3/
./configure && install
检查是否安装好(显示安装好的版本号就是已经安装好了)并创建软链接。 expect -v
[root@localhost shell]# expect -v
expect version 5.45.3
2.expect常用的参数选项 2.1? 使用 -c 选项:在命令行运行expect 脚本。 示例: [root@localhost shell]# expect -c 'expect "hi expect" {send "hi shelln"}'
hi expect
hi shell
[root@localhost shell]#
解释下:这个的意思就是当我们输入了"hi expect"后,系统输出"hi shell"表示回应,在"hi shell"后加"n"是为了让显示更为直观。 注意一点就是我们在输入完"hi expect"后要按换行键才会出来"hi shell". 2.2 使用 -d 选项:显示调试信息。 示例脚本: [root@localhost shell]# cat ssh.exp
#!/usr/bin/expect -d
set timeout 30
spawn ssh-copy-id 192.168.123.218
expect {
"*yes/no" {send yesr"; exp_continue}
password:123456r}
}
expect eof
当我运行它的时候,显示的信息(主要信息是加粗字体): expect version 5.45
argv[0] = /usr/bin/expect argv[1] = -d argv[2] = ./.exp
set argc 0
set argv0 ./ssh.exp
set argv ""
executing commands from command file ./.exp
spawn
parent: waiting for sync byte
parent: telling child to go ahead
parent: now unsynchronized from child
spawn: returns {130244}
expect: does "" (spawn_id exp6) match glob pattern "? no
no
/usr/bin/id: INFO: Source of key(s) to be installed: /root/.ssh/id_rsa.pub
expect: does /usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pubrn" (spawn_id exp6) match glob pattern no
The authenticity of host 192.168.123.218 (192.168.123.218)' cant be established.
ECDSA key fingerprint is SHA256:Qh+4R5mpwlU6kK3bf0k53ngm+WpKKnfvL1ZJo+YM3ic.
ECDSA key fingerprint is MD5:d2:76:6d:33:17:e1:51:83:13:aa:10:ce:f7:1f:9f:32.
Are you sure you want to continue connecting (yes/no)?
expect: does rnThe authenticity of host '192.168.123.218 (192.168.123.218)' can't be established.rnECDSA key fingerprint is SHA256:Qh+4R5mpwlU6kK3bf0k53ngm+WpKKnfvL1ZJo+YM3ic.rnECDSA key fingerprint is MD5:d2:76:6d:33:17:e1:51:83:13:aa:10:ce:f7:1f:9f:32.rnAre you sure you want to continue connecting (yes/no)? yes
expect: set expect_out(0,string) rnThe authenticity of host '192.168.123.218 (192.168.123.218)' can't be established.rnECDSA key fingerprint is SHA256:Qh+4R5mpwlU6kK3bf0k53ngm+WpKKnfvL1ZJo+YM3ic.rnECDSA key fingerprint is MD5:d2:76:6d:33:17:e1:51:83:13:aa:10:ce:f7:1f:9f:32.rnAre you sure you want to continue connecting (yes/no
expect: set expect_out(spawn_id) exp6
expect: set expect_out(buffer)
send: sending " to { exp6 }
expect: continuing expect
expect: does )? no
yes
expect: does )? yesrnid: INFO: attempting to log in with the new key(s),to filter out any that are already installed
expect: does )? yesrn/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s),to filter out any that are already installedrnid: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
expect: does no
root@123.218s password:
expect: does )? yesrn/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s),to filter out any that are already installedrn/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keysrnroot@192.168.123.218's password: to { exp6 }
Number of key(s) added: 1
Now try logging into the machine,with: ssh '192.168.123.218'
and check to make sure that only the key(s) you wanted were added.
expect: read eof
expect: set expect_out(spawn_id) rnrnNumber of key(s) added: 1rnrnNow try logging into the machine,1)">ssh 192.168.123.218'"rnand check to make sure that only the key(s) you wanted were added.rnrn"
还有一些其他参数,但是我觉得对于我用处不大,所以没有在此记录。 3.expect脚本示例 简单在这记录下下面会用到的一些命令 set timeout?? ? #设置超时时间,默认超时时间10s. spawn shell command # spawn后面接的是我们要执行的shell命令 expect "hi" #匹配输出内容“hi” {send “hellor”}? ? ? ? ? ? ? ? ? ? # 匹配到内容''hi"后输出“hello”,“r”是代表是返回字符。 interact ? ? #执行完成后保持交互状态,把控制权交给控制台,这个时候就可以手工操作了。如果没有这一句登录完成后会退出,而不是留在远程终端上。如果你只是登录过去执行一段命令就退出,可改为[expect eof]? 3.1 简单更改密码脚本 [root@localhost shell]# cat password.exp
#!/usr/bin/expect -d #"#!/usr/bin/expect"这一行告诉操作系统脚本里的代码使用那一个shell来执行。 -d 启用调试模式(可加可不加)。
3.2登陆远程服务器并停留在远程服务器上 [root@localhost shell]# login.exp
#!/usr/bin/expect
spawn 123.218 #ssh 远程登陆;exp_continue} #匹配输出内容,返回内容,exp_continue表示继续执行下一步
*password}
}
interact #执行完成后保持交互状态,把控制权交给控制台,这个时候就可以手工操作了。如果没有这一句登录完成后会退出,而不是留在远程终端上。如果你只是登录过去执行一段命令就退出,可改为[expect eof]
3.3传输参数执行登陆 [root@localhost shell]# login2.exp #!/usr/bin/expect set ip [lindex $argv ] #这条命令是将变量ip的值设置为传入进来的第一个参数。[lindex $argv 0]表示的就是第一个参数的值 set port [lindex $argv ] #这条命令是将变量port的值设置为传入进来的第二个参数。1]表示的就是第二个参数的值 set passwd 123456ssh $ip -p$port #使用变量,这里使用的方法跟shell脚本一样 expect { yes/no;exp_continue} $passwdr} } interact [root@localhost shell]# ./login2.exp 123.218 22 #多个参数直接以空格间隔,第一个参数:192.168.123.218 第二个参数22 ? 3.4在shell脚本中使用expect 3.4.1通过添加expect脚本文件(建议这种) 实现的功能:输入ip(也就是我们传入的参数),并登陆到这个ip,并保持交互状态(interact)。 login.sh脚本内容(shell) [root@localhost shell]# login.sh
#!/bin/bash
read -p please input you ip:" -t30 remote_ip #获取登陆ip内容
echo $remote_ip
./login.exp $remote_ip #运行expect脚本 传入参数
? login.exp脚本内容(expect) [root@localhost shell]# expect
set ip [lindex $argv ] #将参数值传递给变量ip
spawn $ip #登陆ip
expect {
;exp_continue} #匹配登陆信息,返回'yes'
"123456r} #匹配输出信息,返回密码
}
interact #登陆成功后并保持交互状态,把控制权交给控制台
3.4.2在shell脚本直接写入expect命令 #!/bin/
expect -d <<EOF
spawn $remote_ip
expect {
;exp_continue}
*password:Xuansiwei123!r}
}
exit
expect eof;
EOF
3.4.3 expect匹配不同情况(有密钥文件则退出,没有则添加) sshkey.exp #!/usr/bin/expect -d spawn ssh-keygen.ssh/id_rsaOverwrite (y/n)? exit #判断是否已经有密钥文件,有则退出,没有就进行添加。 Enter passphraseEnter same passphrase again:} } expect eof ? 3.5批量分发公钥到远程主机 批量分发我主要有三个文件,第一个是ip.txt(用来储存ip和密码的,ip和密码直接以":"间隔,示例:192.168.123.12:123456),第二个文件是add.sh(包含读取ip.txt和批量添加的脚本),第三个文件是?ssh_copy.exp(用来处理交互的脚本) ip.txt文件内容 #ip password
123.110:123456
123.111:123@456!
这里注意下我第二行的ip的密码的最后一位是“!”,它在我shell脚本中的取出密码步骤也给我造成了一点麻烦,直接echo "$i"是报错的,我后面换成了echo "${i}",这样就不会报错了。 add.sh(shell脚本) #!/bin/bash
IP_file=/root/shell/ip.txt'
if [ -e $IP_file ] #检查ip.txt文件是否存在,
then
echo -e |