“shell是世界上最好的脚本语言!”🌚🌚🌚
shell脚本虽然可以很方便的帮我处理一些琐碎的问题,但同时也有它的缺点:shell脚本是一种无交互式的脚本
什么叫无交互式呢,比如说删除这个命令
[[email protected] ~]# rm test
rm:是否删除普通文件 "test"?
在删除一个文件时,系统会给一条交互信息询问是否要删除文件,所以删除一个文件需要有两个操作:删除->确认删除(当然你也可以加-f来强制删除就不会有这个交互过程了,这里只是举一个例子),而shell执行命令时实际上只能一条一条的执行,并不能处理这些交互过程
所以这就引出了本文的主角:expect,一种交互式的脚本工具
其他我就不多说了,直接来将expect怎么使用吧
- 安装:
yum install expect
- 编写expect脚本:
- 脚本名一般以
结尾.exp
- 第一行为
#!/usr/bin/expect
- 脚本名一般以
- 定义变量:
-
set 变量名 值
-
:从命令参数数组中取值set 变量名 [lindex $argv 0]
- 特殊变量:
-
:参数个数,相当于shell中的$argc
$#
-
:所有参数的数组,索引从0开始$argv
-
-
- 语句:
-
set 定义变量
-
:将超时时间设置成300(秒)set timeout 300
-
-
:监控命令的输出spawn COMMAND
-
:捕获输出,并执行相应命令expect “STRING” { send “STRING” }
-
:发送“STRING”,比如删除文件时需要回复yes表示确认删除,就可以写send “STRING\r”
,注意最后需要换行,不然输出结果看起来会比较乱send “yes\r”
-
:执行expect时前台会被占用,这里相当于在执行完脚本中的某一个任务时发给终端的一条提示,相当于shell中的send_user “STRING”
echo
-
:继续捕获输出,expect用{}框起来的块中可以实现类似case的判断效果,这里的exp_continue就相当于case语句中每一判断条件的breakexp_continue
-
:暂停脚本的执行,将控制权交还给用户,直到用户interact
-
:退出脚本exit
-
:捕获退出信号,若捕获不到则会阻塞等待,超时自动退出expect eof
-
下面是一些相关例子:
模拟ftp登录并下载文件
- 工作准备:
- 关闭防火墙:
iptable -F
-
yum install vsftpd
-
systemctl restart vsftpd
-
cp /etc/fstab /var/ftp
-
yum install ftp
- 关闭防火墙:
#!/usr/bin/expect
set ip [lindex $argv 0]
set name "ftp"
set pass ""
set file "fstab"
spawn ftp $ip
expect "Name"
send "$name\r"
expect "Password"
send "$pass\r"
expect ">" {
send "get $file ftp_$file\r"
send "exit\r"
}
expect eof
send_user "ALL COMMAND FINISHDED\n"
测试用例:
[[email protected] ~]# ./ftp.exp 127.0.0.1
spawn ftp 127.0.0.1
Connected to 127.0.0.1 (127.0.0.1).
220 (vsFTPd 3.0.2)
Name (127.0.0.1:root): ftp
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> get fstab ftp_fstab
local: ftp_fstab remote: fstab
227 Entering Passive Mode (127,0,0,1,246,62).
150 Opening BINARY mode data connection for fstab (501 bytes).
226 Transfer complete.
501 bytes received in 0.000192 secs (2609.38 Kbytes/sec)
ftp> exit
221 Goodbye.
ALL COMMAND FINISHDED
[[email protected] ~]#
[[email protected] ~]# ll | grep 'ftp_'
-rw-r--r--. 1 root root 501 3月 5 22:28 ftp_fstab
用shell脚本批量分发公钥(将所有)
- 创建密钥分发expect脚本
key.exp
#!/usr/bin/expect
set timeout 300
set password "redhat"
set ip [lindex $argv 0]
spawn ssh-copy-id [email protected]$ip
expect {
"yes/no" {
send "yes\r"
exp_continue
}
"password: " {
send "$password\r"
exp_continue
}
"No route to host" {
exit 1
}
eof
}
- 创建shell脚本,调用expect
#!/bin/bash
. /etc/init.d/functions
for i in `cat /root/ip.txt`; do
expect /root/key.exp $i > /dev/null 2>&1
if [ $? -eq 0 ]; then
action "$i" /bin/true
else
action "$i" /bin/false
fi
done