针对文本内容进行操作,是标准输入的替代品
不需要进入到文件内部,可以在文件外对文件内容进行操作
命令 <<标记 (命令是linux命令)
内容
标记 #以什么标记,就以什么结尾
注意事项
本身就具有标准输出的作用,可以直接把内容输入到文件当中
建立在tcl语言基础上的工具,自动化控制和测试,解决shell脚本中交互的问题
[root@pup1 opt]# yum -y install expect
#yum安装会自动解决依赖关系,不需安装tcl
执行方式:
当前目录:./
绝对路径:/
常用转义字符
\n | 相当于换行,回车 |
\t | 制表符,即tab键 |
\r | 回车 |
\b | 退格符,即backspace |
#!/usr/bin/expect
spawn后一般都是linux的命令,表示开启会话或开启进程,并跟踪后续的交互信息
例:spawn passwd root (开启给root用户修改密码的命令)
捕获spawn启动命令的相关内容,进行字符串匹配
发送指令,模拟用户的输入
示例:
方式一:
expect "密码" {send "123456\r"} #写在同一行必须要用{}
方式二:
expect"密码"
send "123456\r" #换行写不需要{}
方式三:多分支匹配
expect {
"密码1" {send "123456\r"}
"密码2" {send "123456\r"}
"密码3" {send "123456\r"}
}
表示交互结束,等待执行结束,退回到原用户
默认等待时间为10s,随即退回之前的终端
表示执行完成之后保持交互状态,把控制权交给控制台,然后停留在目标终端不会退回到原终端
注意:两种结束符只能二选一
定义变量,设置参数
expect脚本可以接受从bash命令行传递的参数,使用[lindex $argv n] 获得。其中n从0开始,分别表示第一个, 第二个,第三个…参数
示例:
set timeout 5
#expect默认的超时时间为10s,通过set命令设置超时时间
set hostname [lindex $argv 0]
#相当于hostname=$1
set passwd [lindex $argv 1]
#相当于passwd=$2
和expect捕获命令结合一起使用,附加在expect判断项之后,匹配到expect的捕获内容之后还能够继续判断expext捕获语句内的其他项
格式:
expect {
"connecting (yes/no)" {send "yes\r"; exp_continue;}
}
注意:expect{}外不要直接街上结束符,因为spawn进程结束后会默认向expect发送eof,会导致后面的结束语执行报错
回显命令,相当于echo,即打印
示例1:免交互修改用户密码
[root@pup1 opt]# vim passwd.sh
#!/usr/bin/expect
#定义用expect解释器来执行脚本
set timeout 5
#自定义等待时间
spawn passwd ovo
#开启修改密码的进程
expect "New password:"
#捕获的内容是模拟用户需要输入的内容
send "123456\r"
expect "Retype new password:"
send "123456\r"
expect eof
[root@pup1 opt]# chmod 777 passwd.sh
[root@pup1 opt]# ./passwd.sh
示例2:切换用户
[root@pup1 opt]# vim su.sh
#!/usr/bin/expect
set timeout 5
set username [lindex $argv 0]
set password [lindex $argv 1]
#传参,相当于shell的位置变量
spawn su - $username
#开始追踪命令
expect "Password:"
send "$password\r"
expect "*]#"
send_user "ok"
interact
[root@pup1 opt]# chmod 777 su.sh
[root@pup1 opt]# ./su.sh
将expect免交互的过程和shell结合
ssh、su这类涉及到终端切换的命令不建议使用嵌入执行模式
示例:创建用户并创建密码
[root@pup1 opt]# vim qian.sh
#!/bin/bash
user=$1
password=$2
#不需要交互的命令可以放在expect外面执行
useradd $user
#密码环节开始执行免交互
/usr/bin/expect <<-EOF
#开启执行的标志,仅限于嵌入式
spawn passwd $user
expect "New"
send "${password}\r"
expect "Retype"
send "${password}\r"
expect eof
EOF
[root@pup1 opt]# chmod 777 qian.sh
[root@pup1 opt]# ./qian.sh
示例1:实现ssh自动登录
[root@pup1 opt]# vim ssh.sh
#!/usr/bin/expect
set ip 20.0.0.20
set user root
set password 123
#分别声明好连接的ip地址、用户名和密码
set timeout 5
spawn ssh ${user}@${ip}
#开始捕获ssh [email protected]
expect {
"(yes/no)" {send "yes\n";exp_continue;}
"password" {send "$password\r"}
}
interact
[root@pup1 opt]# chmod 777 ssh.sh
[root@pup1 opt]# ./ssh.sh
示例2:用传参的方式实现ssh自动登录
[root@pup1 opt]# vim ssh2.sh
#!/user/bin/expect
#传参的方式执行,可以自定义用户名及密码
set timeout 5
set username [lindex $argv 0]
set password [lindex $argv 1]
#传参
#开启进程,捕获
spawn ssh $username
#定义捕获文件
expect {
"No route to host" {send_user "主机名或ip有误\n"}
"Connection refused" {send_user "ssh访问请求被拒绝\n"}
"(yes/no)" {send "yes\r";exp_continue;}
"password" {send "$password\r"}
}
interact
#interact后面的命令不会再继续执行
exit
[root@pup1 opt]# chmod 777 ssh2.sh
[root@pup1 opt]# ./ssh2.sh
实例3: 通过免交互的方式实现硬盘分区、格式化、挂载
[root@pup1 opt]# vim fen.sh
#!/bin/bash
x=$1
/usr/bin/expect <<-EOF
spawn fdisk /dev/sd$x
expect "Command (m for help)"
send "n\r"
expect "Select (default p)"
send "p\r"
expect "Partition number (1-4, default 1)"
send "\r"
expect "First sector"
send "\r"
expect "Last sector"
send "+10G\r"
expect "Last sector"
send "w\r"
expect eof
EOF
partprobe /dev/sd$x
mkfs.xfs /dev/sd${x}1
if [ $? -eq 0 ]
then echo "磁盘格式化完成"
mkdir /data
mount /dev/sd${x}1 /data
else echo "磁盘格式化失败"
fi