笔记内容:java
笔记日期:2017-11-29mysql
<br>正则表达式
expect是一个自动化交互式应用程序的工具,因此expect能够用来处理交互的命令。借助expect,咱们能够将交互过程写在一个脚本上,使之自动化完成。形象的说,ssh登陆,ftp登陆等都符合交互的定义。expect含有利用正则表达式进行模式匹配以及通用的编程功能,容许简单的脚本智能地管理以下工具:telnet,ftp和ssh(这些工具都缺乏编程的功能),宏以及其它程序。expect脚本的出现使得这些老的软件工具备了新的功能和更多的灵活性。sql
<br>shell
以上简介中也提到了expect和shell相似,能够进行编程,接下来就实际的编写一些expect脚原本学习expect简单的使用方式。编程
若是你的系统没有安装expect,须要先安装expect,安装命令以下:vim
yum install -y expect数组
expect示例:编写一个自动远程登陆脚本,expect编写的脚本文件后缀名为expect,这是为了好区分:bash
[root@localhost ~]# mkdir expectFiles [root@localhost ~]# cd expectFiles/ [root@localhost ~/expectFiles]# vim telnet_ept.expect #! /usr/bin/expect # 须要登陆的IP set host "192.168.77.128" # 密码 set passwd "123456" # 登陆的命令 spawn ssh root@$host # expect用于执行一些命令 expect { # 初次登陆会询问"yes/no",因此若是截取的是"yes/no"就 send 发送一个yes,\r是回车的意思,exp_continue表示继续 "yes/no" { send "yes\r"; exp_continue} # 若是截取的是"password:"就 send 发送密码 "password:" { send "$passwd\r" } } # 结束标识,可是不会退出登陆,不加interact的话就会立刻退出登陆 interact
set是用来定义一个变量的,变量名后面跟的就是变量的值,不须要使用等于号来赋值,调用变量的方式和shell同样,也是使用$符号。ssh
与interact相对的就是expect eof ,expect eof会在登陆后,停留登陆状态1-2秒后才退出登陆。
执行这个脚本须要加一个执行权限,而后直接执行就能够了:
[root@localhost ~/expectFiles]# chmod a+x telnet_ept.expect [root@localhost ~/expectFiles]# ./telnet_ept.expect spawn ssh root@192.168.77.128 The authenticity of host '192.168.77.128 (192.168.77.128)' can't be established. ECDSA key fingerprint is 4d:5a:9d:31:65:75:30:47:a3:9c:f5:56:63:c4:0f:6a. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added '192.168.77.128' (ECDSA) to the list of known hosts. root@192.168.77.128's password: Last login: Wed Nov 29 14:07:45 2017 from 192.168.77.1 [root@localhost ~]#
运行结果如上,成功登陆了192.168.77.128。
<br>
除了可以实现远程登陆外,还能实现远程执行命令,例如能够写一个自动远程登陆后,执行命令并退出的脚本:
[root@localhost ~/expectFiles]# vim telnet_2.expect #!/usr/bin/expect set user "root" set passwd "123456" spawn ssh $user@192.168.77.128 expect { "yes/no" { send "yes\r"; exp_continue} "password:" { send "$passwd\r" } } # 当遇到 "]#" 就执行sebd命令,咱们登陆后不就是:[root@localhost ~]#,末尾就是 ]# ,而send是发送touch建立文件的命令 expect "]#" send "touch /tmp/12.txt\r" # 一样的当遇到 "]#" 就执行sebd里的命令 expect "]#" send "echo 1212 > /tmp/12.txt\r" # 最后退出系统 expect "]#" send "exit\r"
运行脚本:
[root@localhost ~/expectFiles]# chmod a+x telnet_2.expect [root@localhost ~/expectFiles]# ./telnet_2.expect spawn ssh root@192.168.77.128 root@192.168.77.128's password: Last login: Wed Nov 29 14:54:34 2017 from 192.168.77.130 [root@localhost ~]# touch /tmp/12.txt [root@localhost ~]# echo 1212 > /tmp/12.txt [root@localhost ~]# [root@localhost ~/expectFiles]#
而后再来看看192.168.77.128机器上有没有/tmp/12.txt 文件:
[root@localhost ~]# ll /tmp/12.txt -rw-r--r-- 1 root root 5 11月 29 15:10 /tmp/12.txt [root@localhost ~]# cat !$ cat /tmp/12.txt 1212 [root@localhost ~]#
能够看到文件和内容与脚本中执行的命令一致。
<br>
expect脚本也是能够像shell脚本同样传递参数的,如下例子演示如何拿到脚本的参数:
[root@localhost ~/expectFiles]# vim telnet_3.expect #!/usr/bin/expect # expect脚本拿参数的方式有点像是在数组中拿元素同样,也是从0开始数,$argv是expect的一个内置变量 set user [lindex $argv 0] # 第一个参数 set host [lindex $argv 1] # 第二个参数 set passwd "123456" # 须要远程执行的命令 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@localhost ~/expectFiles]# ./telnet_3.expect root 192.168.77.128 ls spawn ssh root@192.168.77.128 root@192.168.77.128's password: Last login: Wed Nov 29 15:10:48 2017 from 192.168.77.130 [root@localhost ~]# ls \ stop.sh zabbix-release-3.2-1.el7.noarch.rpm anaconda-ks.cfg Test.class mysql57-community-release-el7-8.noarch.rpm Test.java [root@localhost ~]# [root@localhost ~/expectFiles]#
执行多条命令,使用引号将命令括起来便可:
[root@localhost ~/expectFiles]# ./telnet_3.expect root 192.168.77.128 "ls;w;who" spawn ssh root@192.168.77.128 root@192.168.77.128's password: Last login: Wed Nov 29 15:29:30 2017 from 192.168.77.130 [root@localhost ~]# ls;w;who \ stop.sh zabbix-release-3.2-1.el7.noarch.rpm anaconda-ks.cfg Test.class mysql57-community-release-el7-8.noarch.rpm Test.java 15:29:48 up 5:13, 2 users, load average: 0.00, 0.01, 0.05 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT root pts/0 192.168.77.1 14:07 15:00 0.06s 0.06s -bash root pts/1 192.168.77.130 15:29 0.00s 0.02s 0.00s w root pts/0 2017-11-29 14:07 (192.168.77.1) root pts/1 2017-11-29 15:29 (192.168.77.130) [root@localhost ~]# [root@localhost ~/expectFiles]#
关于这种远程执行命令的操做,会存在一个超时时间,也就是说,若是你须要远程执行的那条命令的执行时间,超过了默认的超时时间,命令的执行就会被终止。这个默认的超时时间是10秒,咱们能够经过执行一条vmstat命令来测试出这个默认的超时时间:
[root@localhost ~/expectFiles]# ./telnet_3.expect root 192.168.77.128 "vmstat 1" spawn ssh root@192.168.77.128 root@192.168.77.128's password: Last login: Wed Nov 29 17:25:48 2017 from 192.168.77.130 [root@localhost ~]# vmstat 1 procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 1 0 0 3271556 1376 259272 0 0 4 1 35 64 0 0 100 0 0 0 0 0 3271712 1376 259364 0 0 0 0 92 157 0 0 100 0 0 0 0 0 3271712 1376 259364 0 0 0 0 76 128 0 0 100 0 0 0 0 0 3271744 1376 259364 0 0 0 0 91 146 0 1 100 0 0 0 0 0 3271744 1376 259364 0 0 0 0 64 120 0 0 100 0 0 0 0 0 3271712 1376 259364 0 0 0 0 78 127 0 0 100 0 0 0 0 0 3271712 1376 259364 0 0 0 0 57 104 0 0 100 0 0 0 0 0 3271712 1376 259364 0 0 0 0 81 128 0 1 100 0 0 0 0 0 3271712 1376 259364 0 0 0 0 75 127 0 0 100 0 0 0 0 0 3271200 1376 259400 0 0 0 0 91 153 0 1 100 0 0 0 0 0 3270936 1376 259400 0 0 0 0 92 152 0 0 100 0 0 [root@localhost ~/expectFiles]#
以上运行结果能够看到vmstat设置的间隔时间为1秒,只打印了11行数据就退出登陆了,第一行打印不算在超时时间内,从第二行开始数,恰好是10行,每行打印的间隔时间是1秒,因此就能够知道默认的超时时间是10秒。
那么要如何修改这个默认的超时时间呢?只须要在脚本中加上一句set timeout便可,设置的时间单位为秒,示例:
#!/usr/bin/expect set user [lindex $argv 0] set host [lindex $argv 1] set passwd "Zero-One1." set cm [lindex $argv 2] spawn ssh $user@$host # 设置超时时间为3秒 set timeout 3 expect { "yes/no" { send "yes\r"} "password:" { send "$passwd\r" } } expect "]#" send "$cm\r" expect "]#" send "exit\r"
运行结果:
[root@localhost ~/expectFiles]# ./telnet_3.expect root 192.168.77.128 "vmstat 1" spawn ssh root@192.168.77.128 root@192.168.77.128's password: Last login: Wed Nov 29 17:25:54 2017 from 192.168.77.130 [root@localhost ~]# vmstat 1 procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 1 0 0 3271172 1376 259420 0 0 4 1 35 64 0 0 100 0 0 0 0 0 3270968 1376 259508 0 0 0 0 104 174 0 0 100 0 0 0 0 0 3270936 1376 259560 0 0 0 0 90 152 0 1 100 0 0 0 0 0 3270780 1376 259596 0 0 0 0 83 137 0 0 100 0 0 [root@localhost ~/expectFiles]#
提示:若是你将set timeout的值设置为-1的话,就表示没有超时时间,命令会一直执行。
<br>
expect结合rsync 能够实现自动同步文件,代码示例:
[root@localhost ~/expectFiles]# vim synFile.expect #!/usr/bin/expect set passwd "123456" spawn rsync -av root@192.168.77.128:/tmp/12.txt /tmp/ expect { "yes/no" { send "yes\r"} "password:" { send "$passwd\r" } } expect eof
以上脚本运行结果:
[root@localhost ~/expectFiles]# chmod a+x synFile.expect [root@localhost ~/expectFiles]# ./synFile.expect spawn rsync -av root@192.168.77.128:/tmp/12.txt /tmp/ root@192.168.77.128's password: receiving incremental file list 12.txt sent 30 bytes received 84 bytes 228.00 bytes/sec total size is 5 speedup is 0.04 [root@localhost ~/expectFiles]# cat /tmp/12.txt 1212 [root@localhost ~/expectFiles]#
若是把脚本中的expect eof命令给注释掉,看看会发生什么:
[root@localhost ~/expectFiles]# ./synFile.expect spawn rsync -av root@192.168.77.128:/tmp/12.txt /tmp/ root@192.168.77.128's password: [root@localhost ~/expectFiles]#
从结果能够看到,还没来得及执行rsync命令就退出来了,因此在这种登陆后须要执行命令的expect脚本中必定要加上expect eof或者interact,否则你须要远程执行的命令就会来不及被执行,这就是加不加expect eof或者interact的区别。
可能有些人会想到使用set timeout来设置一个超时时间避免立刻退出登陆,其实是无效的,避免这种立刻退出登陆的方式只能用expect eof或者interact。
<br>
想要指定host和要同步的文件就把它们做为参数就行了:
#!/usr/bin/expect set passwd "123456" 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@localhost ~/expectFiles]# chmod a+x hostFile.expect [root@localhost ~/expectFiles]# ./hostFile.expect 192.168.77.128 "/tmp/12.txt" spawn rsync -av /tmp/12.txt root@192.168.77.128:/tmp/12.txt root@192.168.77.128's password: sending incremental file list sent 31 bytes received 12 bytes 86.00 bytes/sec total size is 5 speedup is 0.12 [root@localhost ~/expectFiles]#
文件的路径要写绝对路径,而后须要使用双引号引发来。