您的位置:首页 > 运维架构 > Linux

linux expect的简单用法及举例

2015-06-28 20:53 706 查看
一、expect简介
我们通过Shell可以实现简单的控制流功能,如:循环、判断等。但是对于需要交互的场合则必须通过人工来干预,有时候我们可能会需要实现和交互程序如telnet服务器等进行交互的功能。而Expect就使用来实现这种功能的工具。
Expect是一个免费的编程工具语言,用来实现自动和交互式任务进行通信,而无需人的干预。Expect的作者Don Libes在1990年 开始编写Expect时对Expect做有如下定义:Expect是一个用来实现自动交互功能的软件套件 (Expect [is a] software suite for automating interactive tools)。使用它系统管理员 的可以创建脚本用来实现对命令或程序提供输入,而这些命令和程序是期望从终端(terminal)得到输入,一般来说这些输入都需要手工输入进行的。 Expect则可以根据程序的提示模拟标准输入提供给程序需要的输入来实现交互程序执行。甚至可以实现实现简单的BBS聊天机器人。
Expect是不断发展的,随着时间的流逝,其功能越来越强大,已经成为系统管理员的的一个强大助手。Expect需要Tcl编程语言的支持,要在系统上运行Expect必须首先安装Tcl。
二、系统环境介绍及安装expect
1、环境介绍
hostnameIP
服务端
webserver192.168.1.2
服务端webserver192.168.1.222
服务端webserver192.168.1.20
客户端
hpf-linux192.168.1.110
2、安装expect
在客户端安装:
[root@hpf-linux ~]# yum install -y expect
在安装过程中会出现同时安装expect包时所依赖的包tcl。
已安装:
expect.i686 0:5.44.1.15-5.el6_4

作为依赖被安装:
tcl.i686 1:8.5.7-6.el6

三、expect脚本的简单应用举例
重要:首先声明所有的expect脚本均提前手动赋予了X执行权限!
1、登陆后,执行命令然后退出的脚本:
[root@hpf-linuxexpect]# cat 1.expect
#!/usr/bin/expect
set user "root"
set passwd "**********"
spawn ssh $user@192.168.1.222
expect {
"yes/no" { send "yes\r"; exp_continue}
"password:" { send "$passwd\r" }
}
expect "]*"
send "touch /tmp/12.txt\r"
expect "]*"
send "echo 1212 > /tmp/12.txt\r"
expect "]*"
send "exit\r"
[root@hpf-linux expect]# ./1.expect
[root@webserver ~]# cat  /tmp/12.txt
1212
上面这个脚本比较简单的使用expect来进行登录远程服务端,并且在服务端/tmp目录创建了一个12.txt文件同时在文件内添加了内容1212。由于这个脚本是明文密码所以会很不安全,所以今后使用还要慎重!

2、还可以手动输入参数来进行执行脚本
[root@hpf-linuxexpect]# cat 2.expect
#!/usr/bin/expect
set user [lindex $argv 0]
set host [lindex $argv 1]
set passwd "*********"
set cm [lindex $argv 2]            //需要执行的命令,若命令间有空格则要用双引号""引起来
spawn ssh $user@$host
expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
expect "]*"
send "$cm\r"
expect "]*"
send "exit\r"
[root@hpf-linux expect]# ./2.expect root 192.168.1.222 "ls -l /tmp/12.txt"
spawn ssh root@192.168.1.222
root@192.168.1.222's password:
Last login: Sun Jun 28 18:18:55 2015 from 192.168.1.110
[root@webserver ~]# ls -l /tmp/12.txt
-rw-r--r-- 1 root root 5 6月  28 18:18 /tmp/12.txt
3、自动同步脚本内所定义的文件或者目录
下面的例子需要两台机器安装的rsync同步命令,不然无法正常传输。

[root@hpf-linuxexpect]# cat 3.expect
#!/usr/bin/expect
set passwd "**********"
spawn rsync -av  /tmp/    //将远程机器上指定文件的内容同步到本机/tmp上
expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
expect eof
[root@hpf-linux expect]# ./3.expect
spawn rsync -av root@192.168.1.222:/tmp/12.txt /tmp/
root@192.168.1.222's password:
receiving incremental file list
12.txt

sent 30 bytes  received 84 bytes  76.00 bytes/sec
total size is 5  speedup is 0.04
[root@hpf-linux expect]# ls -l /tmp/12.txt
-rw-r--r-- 1 root root 5 6月  28 2015 /tmp/12.txt
4、指定IP和要同步的文件
[root@hpf-linuxexpect]# cat 4.expect
#!/usr/bin/expect
set passwd "*********"
set host [lindex $argv 0]
set file [lindex $argv 1]
spawn rsync -av $file root@$host:$file
expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
expect eof
[root@hpf-linux expect]# echo "longls"> /tmp/12.txt
[root@hpf-linux expect]# ./4.expect 192.168.1.222 /tmp/12.txt //同步客户端/tmp/12.txt中的内容到指定IP机器上
spawn rsync -av /tmp/12.txt root@192.168.1.222:/tmp/12.txt
root@192.168.1.222's password:
sending incremental file list
12.txt

sent 81 bytes  received 37 bytes  236.00 bytes/sec
total size is 7  speedup is 0.06
[root@hpf-linux expect]# ./2.expect root 192.168.1.222 "cat /tmp/12.txt"     //查看是否同步成功
spawn ssh root@192.168.1.222
root@192.168.1.222's password:
Last login: Sun Jun 28 18:25:05 2015 from 192.168.1.110
[root@webserver ~]# cat /tmp/12.txt
longls
四、构建文件分发系统
实验需求:
由于公司的代码更新,需要将你管理的几十台机器的相关文件进行同步更新,我们可以用自动化运维工具puppet来实现,也可以自己一个个的用rsync进行同步,也可以用expect结合shell脚本进行同步处理,目前三种方法都有其优缺点,用puppet运维工具很高大上,但需要的运维人员经验较高,自己用rsync虽然很简单但是工作效率很低,最后以我目前的水平就使用expect+shell的脚本结合进行做文件同步处理。

实验环境介绍:
1、每台需要同步机器的密码要相同,若都不相同则还要想办法,不过为了快速的进行还是将密码都设置一样;
2、在实验环境的脚本都已经手动的赋予X执行权限;
3、要有一台模板机器,把要分发的文件准备好,然后只要使用expect脚本批量把需要同步的文件分发到目标机器即可;
4、所有脚本都在一个目录内/root/sync/,同时在写同步的文件时都要写绝对路径。

实验脚本:
将一个文件内其列举的所有文件通过脚本一步同步到远程三台机器上:
[root@hpf-linuxsync]# cat ip.list
192.168.1.222
192.168.1.2
192.168.1.20
[root@hpf-linuxsync]# cat movies.txt
/root/cangls/cangls.avi
/root/longls/longls.avi
/root/xiaozels/xiaozels.avi
[root@hpf-linuxsync]# cat rsync.expect
#!/usr/bin/expect
set passwd "***********"
set host [lindex $argv 0]
set file [lindex $argv 1]
spawn rsync -av --files-from=$file / root@$host:/tmp
expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
expect eof
[root@hpf-linux sync]# cat rsync.sh
#!/bin/bash
for ip in `cat ip.list`
do
echo $ip
./rsync.expect $ip movies.txt
done
上述实验需要注意的是rsync -av --files-from=$file / root@$host:/tmp这条命令的意思:根据一个文档中的文件列表来同步文件。同时另外三台机器的都要安装rsync,同时在movies.txt内的文件路径都要有真实的文件。

在一台机器上通过执行脚本可以在多台机器上进执行已在脚本自定义的命令:
[root@hpf-linux sync]# cat exe.expect
#!/usr/bin/expect
set host [lindex $argv 0]
set passwd "**************"
set cm [lindex $argv 1]

spawn ssh root@$host

expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
expect "]*"
send "$cm\r"
expect "]*"
send "exit\r"

[root@hpf-linux sync]# cat exe.sh
#!/bin/bash
for ip in `cat ip.list`
do
echo $ip
./exe.expect $ip "> /tmp/12.txt;date >> /tmp/12.txt;"
done


上面的实验比较简单的在一台机器上通过自定义脚本可以向多台机器进行操作,这个脚本还有可以扩展的部分就是执行的命令可以专门写个脚本在进行嵌套循环执行,我在做这个实验时在脚本 exe.sh 中无法在添加命令了,一添加在执行脚本时就会出错,同时自己也尝试的写了执行命令的脚本,但由于能力有线就没能做出自己想要的结果,今后若将shell中for循环嵌套的脚本学会那就在尝试的完善这个实验。

最后总结:
在现今高度发展的it社会,已经有很多的自动化管理程序了,例如Puppet,Salt,func,Capistrano .......而且还有云虚拟化OpenStack,kvm,xen.....尤其Docker更是新生代黑马,为自动化管理而生的。但存在即为合理,你有高大上,我也有土肥圆,相对于快捷,简单的管理小批量linux机器,ssh和expect是非常好用的。
expect这个工具结合shell脚本可以说是我目前能会的唯一的关于自动化运维方面的知识,由于自己的经验不足还不能继续的写出更完善的shell脚本和小型的自动化运维脚本,今后还要加强练习自己的shell编程能力,以上就是expect工具的简单应用,如有错误请指正!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  shell expect