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软件
# 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
# rpm -qa | grep expect
expect-5.44.1.15-5.el6_4.x86_64
# mkdir /scirts
# cd /scirts/
# vi xp-excpec.exp
# chmod 700 xp-excpec.exp
# cat xp-excpec.exp
#!/usr/bin/expect
spawn ssh -p22 root@192.168.20.5 /sbin/ifconfig eth0
set timeout 60
expect "*password:"
send "ww123123\n"
expect eof
exit
# ./xp-excpec.exp
spawn ssh -p22 root@192.168.20.5 /sbin/ifconfig eth0
root@192.168.20.5's password:
eth0 Link encap:EthernetHWaddr 00:0C:29:D8:5D:8C
inet addr:192.168.20.5Bcast:192.168.20.255Mask:255.255.255.0
inet6 addr: fe80::20c:29ff:fed8:5d8c/64 Scope:Link
UP BROADCAST RUNNING MULTICASTMTU:1500Metric: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 root@192.168.2.5
在spawn命令后面,直接加上要启动的进程、命令等信息,除此之外,spawn还支持其他选项如;
-open启动文件进程,具体说明省略。
-ignore 忽略某些信号,具体说明省略。
a.2 【expect 使用方法:】
expect 表达式 动作 表达式 动作。。。。。。。
expect 命令用于等候一个相匹配内容的输出,一旦匹配上就执行expect后面的动作或命令,这个命令接受几个
特有参数,用的最多的就是-re,表示使用正则表达式的方式匹配,使用起来就像这样;
spawn ssh root@192.168.20.5
expect "password:"{send "ww123123\r"} 从上面的例子可以看出。expect是依附与spawn命令的,当执行ssh命令后,expect就匹配命令执行后的关键字:password:,
如果匹配到关键字就会执行后面包含在{}括号中的exp_send动作,匹配以及动作可以放在二行,这样就不需要使用{}括号了,
就像下面这样,实际完成的功能与上面是一样的;
spawn ssh root@192.168.20.5
expect "password:"
send "xiaoping\r" expect 命令还有一种用法,它可以在一个expect匹配中多次匹配关键字,并给出处理动作,只需要将关键字放在一个大括号
就可以了,当然还有exp_continue.
spawn ssh root@192.168.20.5
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中的特殊符号相同。
spawnssh root@192.168.20.5
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 root@192.168.20.5 /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:字符了。
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
set host
set dir
set password "123123"
#spawn scp /etc/hosts root@192.168.20.1:/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
set host
set dir
set password "123123123" 【Expect 关键字】
expect中的特殊关键字用于匹配过程,代表某些特殊含义或状态,一般用于expect族命令中而不能在外面单独使用,
也可以理解为事件,使用上类似于:
expect eof { }
7.1 eof
eof (end-of-file)关键字用于匹配结束符,比如文件的结束符,TFP传输停止等情况,在这个关键字后跟上动作来做
进一步的控制,特别是FTP交互操作方面,它的作用很大,用一个例子看看:
spawn FTP root@192.168.20.5
expect {
"password:" {exp_send "who am I"}
eof {ftp connet close}
}
interact {} 7.2 【timeout】
timeout 是expect中的一个重要变量,它是一个全局的时间控制开关,你可以通过为这个变量赋值来规定整个expectc操作的
时间,注意这个变量是服务与expect全局的,它不会纠缠某一条命令,即使命令没有任何错误,到时间依然会激活这个变量,但
这个时间到达以后除了激活一个开关之外不会做其他的事情,如何处理脚本编写人员的事情,看看它的实际使用方法:
set timeout 60
spawn ssh root@192.168.20.5
expect "password:" {send "word\r"}
expect timeout {puts "Expect was timeout";return} 上面的处理中。首先将timeout变量设置为60秒,当出现问题的时候程序可能会停止下来,只要到60秒,就会激活下面的timeout
动作,这里我打印一个信息并且停止了脚本的运行,你可以做更多的其他事情,看自己的意思。
在另外一种expect格式中我们还有一种设置timeout变量的方法,看看下面的例子;
spawnssh root@192.168.20.5
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为命令行参数。
表示第1个参数,为第一个到第五个参数。与c语言不一样的地方在于,$argv不包含脚本名字本身。
【实战1】批量分发文件
# 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
# 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
set host
set dir
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
# 【实战2】:使用expect实战批量分发ssh密钥文件
# 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+. |
+-----------------+
# cd .ssh/
# ls -a
...id_dsaid_dsa.pub
# grep \.ssh /etc/ss
ssh/ ssl/
# grep \.ssh /etc/ssh/ssh
ssh_config ssh_host_dsa_key ssh_host_key ssh_host_rsa_key
sshd_config ssh_host_dsa_key.pubssh_host_key.pub ssh_host_rsa_key.pub
# 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
# cp id_dsa.pubid_dsa.pub.back
# mv id_dsa.pub .ssh/authorized_keys
mv: cannot move `id_dsa.pub' to `.ssh/authorized_keys': No such file or directory
# ^C
# mv id_dsa.pub authorized_keys
# ls -a
...authorized_keysid_dsaid_dsa.pub.back
# mv id_dsa
id_dsa id_dsa.pub.back
# mv id_dsa /xp/
# ls -a
...authorized_keysid_dsa.pub.back
# cd ..
# scp -P22 -p .ssh/ root@192.168.20.5:~/
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.
root@192.168.20.5's password:
.ssh: not a regular file
# scp -P22 -p .ssh/ root@192.168.20.5:~/
root@192.168.20.5's password:
.ssh: not a regular file
# scp -P22 -p -r .ssh/ root@192.168.20.5:~/
root@192.168.20.5'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
# ^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
# grep \AuthorizedKeysFile/etc/ssh/sshd_config
#AuthorizedKeysFile .ssh/authorized_keys
# mkdri /server/scripts -p
# 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远程连接,那么就使用普通用户加sudo的方式在结合expect大量分发。
expect可以大量分发查询机器状态
【实战3】
# 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
set host
set dir
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
# cat piliang.sh
#!/bin/bash
for ip in `cat iplist`
do
expect ex-free.exp $ip free -m
done
# cat iplist
192.168.20.5
192.168.20.10 【测试】
# sh piliang.sh
spawn ssh -P22 root@192.168.20.5 free -m
root@192.168.20.5'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 root@192.168.20.10 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)
#
~
页:
[1]