Expect是一个免费的编程工具语言,用来实现自动和交互式任务进行通信,而无需人的干预。
Expect是一个用来实现自动交互功能的软件套件(Expect [is a] software suite for automating interactive tools)。
Expect语言是基于Tcl的
expect它是一个程序,所以它也是需要提前安装才可以使用的
[root@sjserver ~]# yum -y install expect
已加载插件:fastestmirror
Loading mirror speeds from cached hostfile
* base: mirrors.aliyun.com
* extras: mirrors.aliyun.com
* updates: mirrors.aliyun.com
base | 3.6 kB 00:00:00
epel | 4.7 kB 00:00:00
extras | 2.9 kB 00:00:00
updates | 2.9 kB 00:00:00
(1/2): epel/x86_64/updateinfo | 788 kB 00:00:00
(2/2): epel/x86_64/primary_db | 6.1 MB 00:00:01
正在解决依赖关系
--> 正在检查事务
---> 软件包 expect.x86_64.0.5.45-14.el7_1 将被 安装
例1:ssh无交互登录到远程服务器
[root@sjserver ~]# vim expect.sh
#!/usr/bin/expect //这里需要用expect自己的解释器,注意不要写成bash否则无法识别
spawn ssh [email protected] //开启一个程序,这个程序是ssh远程登录
expect { //捕获内容,当出现password的时候,就会向程序发送密码,默认是不换行的,所以需要\r回车换行,多个条件需要花括号括起来
"password:"
{ send "123456\r"; }
}
interact //交互,否则会直接退出远程服务器
[root@sjserver ~]# chmod +x expect.sh //需要加执行权限
[root@sjserver ~]# ./expect.sh
spawn ssh [email protected]
[email protected]'s password:
Last login: Mon Jul 27 23:31:00 2020 from 192.168.100.120
[root@server ~]#
定义和引用变量
用set关键字定义变量,变量名和变量的值中间用空格分开,其他用法与shell脚本一致
[root@sjserver ~]# vim expect.sh
#!/usr/bin/expect
set ip 192.168.100.100
set username root
set password 123456
spawn ssh $username@$ip
expect {
"password:"
{ send "$password\r"; }
}
interact
给expect脚本添加一些其他参数,如超时时间,日志等
#!/usr/bin/expect
#超时时间
set timeout 20
#开启日志文件
log_file test.log
#显示信息
log_user 1
set ip 192.168.100.100
set username root
set password 123456
spawn ssh $username@$ip
expect {
"password:"
{ send "$password\r"; }
}
interact
查看指定的日志文件
[root@sjserver ~]# vim test.log
spawn ssh [email protected]
[email protected]'s password:
Last login: Tue Jul 28 00:25:00 2020 from 192.168.100.120^M
^[]0;root@server:~^G^[[?1034h[root@server ~]#
^[]0;root@server:~^G[root@server ~]#
^[]0;root@server:~^G[root@server ~]# exit
登出
Connection to 192.168.100.100 closed.^M
远程登录服务器之后可以进行一些操作然后退出都可以免交互
[root@sjserver ~]# vim expect.sh
#!/usr/bin/expect
set ip 192.168.100.100
set username root
set password 123456
spawn ssh $username@$ip
expect {
"password:"
{ send "$password\r"; }
}
expect "#" //当捕获到#号时
send "ls\r" //查看一下当前目录
send "exit\r" //退出登录
expect eof //不需要进行交互了,意味着结束expect程序
运行结果:
[root@sjserver ~]# ./expect.sh
spawn ssh root@192.168.100.100
root@192.168.100.100's password:
Last login: Tue Jul 28 00:26:13 2020 from 192.168.100.120
[root@server ~]# ls
123123 a.out for2.sh initial-setup-ks.cfg oushu.sh ssh.sh :wq 图片
123123.pub dead.letter for3.sh jindu.sh paixu1.sh test.log zhengze.sh 文档
1.sh expect1.sh for4.sh jishuhe.sh paixu2.sh unset.sh 公共 下载
1.txt expect.sh for.sh max.sh root@192.168.100.200 user.sh 模板 音乐
anaconda-ks.cfg for1.sh ifcfg-ens33 ntpdate.sh shanchu.sh while.sh 视频 桌面
[root@server ~]# exit
登出
Connection to 192.168.100.100 closed.
引用位置变量传参给expect脚本
[root@sjserver ~]# vim expect.sh
#!/usr/bin/expect
set username root
set hostname [lindex $argv 0] //这里定义了第一个位置变量为hostname就是ip地址
set password [lindex $argv 1] //这里定义了第二个位置变量为密码
spawn ssh $username@$hostname
expect {
"password:"
{ send "$password\r"; }
}
interact
[root@sjserver ~]# ./expect.sh 192.168.100.100 123456
spawn ssh [email protected]
[email protected]'s password:
Last login: Tue Jul 28 00:31:08 2020 from 192.168.100.120
[root@server ~]#
在shell脚本里引用expect程序,无交互的创建一个用户并为其设置密码
[root@server ~]# vim user.sh
#!/bin/bash
username=$1
useradd $username
/usr/bin/expect <<-EOF
spawn passwd $username
expect {
"密码" //注意:获取的内容和发送的内容不能在同一行否则执行不成功
{send "123456\r";exp_continue}
"新的密码"
{send "123456\r";}
}
EOF
[root@server ~]# . user.sh wangwu
spawn passwd wangwu
更改用户 wangwu 的密码 。
新的 密码:
无效的密码: 密码少于 8 个字符
重新输入新的 密码:
passwd:所有的身份验证令牌已经成功更新。
例2:在shell中调用expect程序,ssh远程到服务器上
[root@server ~]# vim expect1.sh
#!/bin/bash
expect -c "
spawn ssh [email protected]
expect \"*password:*\" { send \"123456\r\"}
interact
"
[root@server ~]# ./expect1.sh
spawn ssh [email protected]
[email protected]'s password:
Activate the web console with: systemctl enable --now cockpit.socket
Last login: Wed Jul 29 09:45:43 2020 from 192.168.100.100
[root@dnsserver ~]#
注意:如果要停留在远程服务器上进行交互操作的话,需要在shell脚本里使用expect -c来调用expect程序,然后再使用interact命令,如果用EOF的话使用interact无效,始终只能无交互
send:向进程中发送字符串
expect:从进程中读取字符串,例如可以读取用户登录的密码等
spawn:此命令可以启动新的进程操作
interact:表示允许用户进行交互操作,一直保持会话连接
exp_continue:脚本继续向下执行指令,如果这个结果不匹配就再继续查看下一个指定是否匹配