linux expect案例用法
EXPECT 用法
expect是基于TCL的相对简单的一个免费脚本编程工具语言,用来实现自动和交互式任务进行通信,无需人的
手工干预,比如ssh\FTP等,这些程序正常情况都需要手工与它们进行交互,而使用EXPECT就可以模拟人手工交互的过程,实现自动的
和远程的程序交互,从而达到自动化的目的。
EXPECT是一个用来实现自动交互功能的软件套件(EXPECT is a software suite for automating interactive tools)
虽然,使用C、perl等一样可以实现这样的功能,而expect做的更加专业出色、简单、而且除支持unix/linux平台外,它还支持
windows平台,它就是为系统管理和软件测试方面的自动交互类需求而产生的。
2.expect程序工作流程
expect的工作流程可以理解为,spawn启动进程-->expect期待关键字---->send向进进程发送字符--->退出结束。
3.安装EXPECT软件
[root@clientC ~]# yum install expect -y Loaded plugins: fastestmirror, refresh-packagekit Determining fastest mirrors * base: mirror.bit.edu.cn * extras: ftp.sjtu.edu.cn * updates: mirrors.hust.edu.cn base | 3.7 kB 00:00 base/primary_db | 4.6 MB 00:00 [root@clientC ~]# rpm -qa | grep expect expect-5.44.1.15-5.el6_4.x86_64 [root@clientC ~]# mkdir /scirts [root@clientC ~]# cd /scirts/ [root@clientC scirts]# vi xp-excpec.exp [root@clientC scirts]# chmod 700 xp-excpec.exp [root@clientC scirts]# cat xp-excpec.exp #!/usr/bin/expect spawn ssh -p22 [email protected] /sbin/ifconfig eth0 set timeout 60 expect "*password:" send "ww123123\n" expect eof exit [root@clientC scirts]# ./xp-excpec.exp spawn ssh -p22 [email protected] /sbin/ifconfig eth0 [email protected]‘s password: eth0 Link encap:Ethernet HWaddr 00:0C:29:D8:5D:8C inet addr:192.168.20.5 Bcast:192.168.20.255 Mask:255.255.255.0 inet6 addr: fe80::20c:29ff:fed8:5d8c/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:9392 errors:0 dropped:0 overruns:0 frame:0 TX packets:2518 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:952097 (929.7 KiB) TX bytes:461897 (451.0 KiB)
【EXPECT语法】
Expect中的 命令是最重要的部分了,命令的使用语法如下;
命令{选项} 参数
a.1.【spawn】
spawn命令是expect的初始命令,它用于启动一个进程,之后所有expect操作都在这个进程中进行,如果
没有spawn语句,整个expect就无法执行了,spawn使用方法如下;
spawn ssh [email protected]
在spawn命令后面,直接加上要启动的进程、命令等信息,除此之外,spawn还支持其他选项如;
-open 启动文件进程,具体说明省略。
-ignore 忽略某些信号,具体说明省略。
a.2 【expect 使用方法:】
expect 表达式 动作 表达式 动作。。。。。。。
expect 命令用于等候一个相匹配内容的输出,一旦匹配上就执行expect后面的动作或命令,这个命令接受几个
特有参数,用的最多的就是-re,表示使用正则表达式的方式匹配,使用起来就像这样;
spawn ssh [email protected] expect "password:"{send "ww123123\r"}
从上面的例子可以看出。expect是依附与spawn命令的,当执行ssh命令后,expect就匹配命令执行后的关键字:password:,
如果匹配到关键字就会执行后面包含在{}括号中的exp_send动作,匹配以及动作可以放在二行,这样就不需要使用{}括号了,
就像下面这样,实际完成的功能与上面是一样的;
spawn ssh [email protected] expect "password:" send "xiaoping\r"
expect 命令还有一种用法,它可以在一个expect匹配中多次匹配关键字,并给出处理动作,只需要将关键字放在一个大括号
就可以了,当然还有exp_continue.
spawn ssh [email protected] expect { "yes/no"{exp_send "yes\r";exp_continue} "*password:" {exp_send "123123\r"} }
a.3【exp_send和send】
在上面的介绍中,我们已经看到exp_send命令的使用,exp_send命令是expect中的动作命令,它还有一个完成同样工作的
同胞:send,exp_send命令可以发送一些特殊符号,我们看到了\r(回车),还有一些其他的比如:\n(换行)、\t(制表符)等等
这些都是与TCL中的特殊符号相同。
spawn ssh [email protected] expect { "yes/no" {send "yes\r";exp_continue} "*password:" {exp_send "123456\r"} }
send命令有几个可用的参数;
-i 指定spawn_id,这个参数用来向不同spawn_id的进程发送命令,是进行多程序控制的关键参数。
-s s代表slowly,也就是控制发送的速度,这个参数使用的时候要与expect中的变量send_slow相关联。
a.4【exp_continue】
这个命令一般用在动作中,它被使用的条件比较苛刻,看看下面的例子;
#!/usr/bin/expect spawn ssh -p22 [email protected] /sbin/ifconfig eth0 set timeout 60 expect { -timeout 1 "yes/no" { exp_send "yes\r";exp_continue } "*password:" {exp_send "123456\r"} timeout {puts "expect was timeout by xiaoping.";return} } expect eof exit
在这个例子中,可以发现exp_continue命令的使用方法,首先它要处于一个expect命令中,然后它属于一种动作命令
完成的工作就是从头开始偏历,也就是说如果没有这个命令,匹配第一个关键字以后就会继续匹配第二关键字,但有了这个
命令后,匹配第一个关键字以后,第二次匹配依然从第一个关键字开始。
A.5【send_user】
send_user 命令用来把后面的参数输出到标准输出中去,默人的send、exp_send 命令都是将参数输出到程序中去的,
用起来就像这样;
send_user "please input passwd:" 这个语句就可以在标准输出中打印please input passwd:字符了。 [root@~]vi xp_3.exp #!/usr/bin/expect if { $argc != 3 } { send_user "usage:expect scp-expect.exp file host dir\n" exit } #define var set file [lindex $argv 0] set host [lindex $argv 1] set dir [lindex $argv 2] set password "123123" #spawn scp /etc/hosts [email protected]:/etc/hosts spawn scp -p22 $file root@$host:$dir expect { "yes/no" {send "yes\r";exp_continue} "*password" {send "$password\r"} timeout {puts "expect connect timeout,pls contact xp";return} } expect eof exit -onexit { send_user "xiaoping say good bye to you!\n" } #expect xiaoping.exp
【Expect 变量】
expect中有很多有用的变量,它们的使用方法与TCL语言中的变量相同,比如:
set 变量名 变量值 #设置变量的方法
puts $变量名 #读取变量的方法
#define var set file [lindex $argv 0] set host [lindex $argv 1] set dir [lindex $argv 2] set password "123123123"
【Expect 关键字】
expect中的特殊关键字用于匹配过程,代表某些特殊含义或状态,一般用于expect族命令中而不能在外面单独使用,
也可以理解为事件,使用上类似于:
expect eof { }
7.1 eof
eof (end-of-file)关键字用于匹配结束符,比如文件的结束符,TFP传输停止等情况,在这个关键字后跟上动作来做
进一步的控制,特别是FTP交互操作方面,它的作用很大,用一个例子看看:
spawn FTP [email protected] expect { "password:" {exp_send "who am I"} eof {ftp connet close} } interact {}
7.2 【timeout】
timeout 是expect中的一个重要变量,它是一个全局的时间控制开关,你可以通过为这个变量赋值来规定整个expectc操作的
时间,注意这个变量是服务与expect全局的,它不会纠缠某一条命令,即使命令没有任何错误,到时间依然会激活这个变量,但
这个时间到达以后除了激活一个开关之外不会做其他的事情,如何处理脚本编写人员的事情,看看它的实际使用方法:
set timeout 60 spawn ssh [email protected] expect "password:" {send "word\r"} expect timeout {puts "Expect was timeout";return}
上面的处理中。首先将timeout变量设置为60秒,当出现问题的时候程序可能会停止下来,只要到60秒,就会激活下面的timeout
动作,这里我打印一个信息并且停止了脚本的运行,你可以做更多的其他事情,看自己的意思。
在另外一种expect格式中我们还有一种设置timeout变量的方法,看看下面的例子;
spawn ssh [email protected] expect { -timeout 60 -re "password:" {exp_send "word\r"} -re "Topsecos#" { } timeout {puts "Expect was timeout";return} }
在expect命令中间加上一个小横杆,也可以设置timeout变量
timeout 变量中,设置为0表示立即超时,-1则表示永久不超时。
expect { -timeout 20 "yes/no" {send "yes\r";exo_continue} "*password" {send "$password\r"} timeout {puts "expect connet timeout ,pls contact xp";return} }
expect的命令行参数参考了c语言的,与bash shell有点不一样。其中,$argc为命令行参数的个数,$argv0为脚本名字本身,$argv为命令行参数。
[lrange $argv 0 0]表示第1个参数,[lrange $argv 0 4]为第一个到第五个参数。与c语言不一样的地方在于,$argv不包含脚本名字本身。
【实战1】批量分发文件
[root@clientC scirts]# cat fenfa_hosts.sh #!/bin/sh . /etc/init.d/functions #调用fuctions函数 for ip in `cat iplist` do expect xp-scp.exp /etc/hosts $ip /xp >/dev/null 2>&1 #可以修改别的拷贝文件 if [ $? = 0 ];then action "$ip" /bin/true else action "$ip" /bin/false fi done [root@clientC scirts]# cat xp-scp.exp #!/urs/bin/expect -f if { $argc != 3 } { send_user "usage: expect xp-scp.exp file host dir\n" exit } #define var set file [lindex $argv 0] set host [lindex $argv 1] set dir [lindex $argv 2] set password "ww123123" spawn scp -P22 -p $file roor@$host:$dir set timeout 10 expect { -timeout 2 "yes/no" {send "yes\r" ;exp_continue} "*password:" {send "$password\r"} timeout {puts "expect connect timeout,pls contact xp"; retur} } expect eof exit [root@clientC scirts]#
【实战2】:使用expect实战批量分发ssh密钥文件
[root@clientC ~]# ssh-keygen -t dsa Generating public/private dsa key pair. Enter file in which to save the key (/root/.ssh/id_dsa): Created directory ‘/root/.ssh‘. Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /root/.ssh/id_dsa. Your public key has been saved in /root/.ssh/id_dsa.pub. The key fingerprint is: 2a:e1:3a:1a:b1:ec:eb:95:e5:16:d7:bb:7a:e2:88:87 root@clientC The key‘s randomart image is: +--[ DSA 1024]----+ | | | | | | | . | |. .o .S. | |.o .+.o. . | |o. o+o. . | |..oEoo.. .. | |o=oo...o+. | +-----------------+ [root@clientC ~]# cd .ssh/ [root@clientC .ssh]# ls -a . .. id_dsa id_dsa.pub [root@clientC .ssh]# grep \.ssh /etc/ss ssh/ ssl/ [root@clientC .ssh]# grep \.ssh /etc/ssh/ssh ssh_config ssh_host_dsa_key ssh_host_key ssh_host_rsa_key sshd_config ssh_host_dsa_key.pub ssh_host_key.pub ssh_host_rsa_key.pub [root@clientC .ssh]# grep \.ssh /etc/ssh/sshd_config # $OpenBSD: sshd_config,v 1.80 2008/07/02 02:24:18 djm Exp $ # This is the sshd server system-wide configuration file. See # sshd_config(5) for more information. # This sshd was compiled with PATH=/usr/local/bin:/bin:/usr/bin # The strategy used for options in the default sshd_config shipped with [root@clientC .ssh]# cp id_dsa.pub id_dsa.pub.back [root@clientC .ssh]# mv id_dsa.pub .ssh/authorized_keys mv: cannot move `id_dsa.pub‘ to `.ssh/authorized_keys‘: No such file or directory [root@clientC .ssh]# ^C [root@clientC .ssh]# mv id_dsa.pub authorized_keys [root@clientC .ssh]# ls -a . .. authorized_keys id_dsa id_dsa.pub.back [root@clientC .ssh]# mv id_dsa id_dsa id_dsa.pub.back [root@clientC .ssh]# mv id_dsa /xp/ [root@clientC .ssh]# ls -a . .. authorized_keys id_dsa.pub.back [root@clientC .ssh]# cd .. [root@clientC ~]# scp -P22 -p .ssh/ [email protected]:~/ The authenticity of host ‘192.168.20.5 (192.168.20.5)‘ can‘t be established. RSA key fingerprint is c1:28:b4:c3:f6:3d:85:bf:b2:df:59:17:d5:9f:65:2e. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added ‘192.168.20.5‘ (RSA) to the list of known hosts. [email protected]‘s password: .ssh: not a regular file [root@clientC ~]# scp -P22 -p .ssh/ [email protected]:~/ [email protected]‘s password: .ssh: not a regular file [root@clientC ~]# scp -P22 -p -r .ssh/ [email protected]:~/ [email protected]‘s password: id_dsa.pub.back 100% 602 0.6KB/s 00:00 authorized_keys 100% 602 0.6KB/s 00:00 known_hosts 100% 394 0.4KB/s 00:00 [root@clientC ~]# ^C #HostKey /etc/ssh/ssh_host_key #HostKey /etc/ssh/ssh_host_rsa_key #HostKey /etc/ssh/ssh_host_dsa_key #AuthorizedKeysFile .ssh/authorized_keys # For this to work you will also need host keys in /etc/ssh/ssh_known_hosts # Change to yes if you don‘t trust ~/.ssh/known_hosts for #PidFile /var/run/sshd.pid Subsystem sftp /usr/libexec/openssh/sftp-server [root@clientC .ssh]# grep \AuthorizedKeysFile /etc/ssh/sshd_config #AuthorizedKeysFile .ssh/authorized_keys [root@clientC ~]# mkdri /server/scripts -p [root@clientC scripts]# cat fenfa_sshkey.sh #!/bin/sh . /etc/init.d/functions for ip in `cat iplist` do expect ex-ssh.exp ~/.ssh/ $ip ~/.ssh/ >/dev/null 2>&1 if [ $? = 0 ];then action "$ip" /bin/true else action "$ip" /bin/false fi done [root@clientC scripts]# 特别提示:如果是禁止了root远程连接,那么就使用普通用户加sudo的方式在结合expect大量分发。 expect可以大量分发查询机器状态 【实战3】 [root@clientC scripts]# cat ex-free.exp #!/urs/bin/expect if { $argc != 3 } { send_user "usage: expect xp-scp.exp file host dir\n" exit } #define var set file [lindex $argv 0] set host [lindex $argv 1] set dir [lindex $argv 2] set password "123456" #spawn scp -P22 -p -r $file roor@$host:$dir spawn ssh -P22 root@$file $host $dir set timeout 10 expect { -timeout 10 "yes/no" {send "yes\r" ;exp_continue} "*password:" {send "$password\r"} timeout {puts "expect connect timeout,pls contact xp";return} } expect eof exit [root@clientC scripts]# cat piliang.sh #!/bin/bash for ip in `cat iplist` do expect ex-free.exp $ip free -m done [root@clientC scripts]# cat iplist 192.168.20.5 192.168.20.10
【测试】
[root@clientC scripts]# sh piliang.sh spawn ssh -P22 [email protected] free -m [email protected]‘s password: total used free shared buffers cached Mem: 199 184 15 0 57 18 -/+ buffers/cache: 107 92 Swap: 1055 0 1055 spawn ssh -P22 [email protected] free -m ssh: connect to host 192.168.20.10 port 22: No route to host expect: spawn id exp4 not open while executing "expect eof" (file "ex-free.exp" line 20) [root@clientC scripts]#
~
本文出自 “小k” 博客,请务必保留此出处http://zyp88.blog.51cto.com/1481591/1615029
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。