2018-08-01 课后笔记

20.27 分发系统介绍

介绍 expect 使用场景

expect可以让我们实现自动登录远程机器,并且可以实现自动远程执行命令。当然若是使用不带密码的密钥验证同样可以实现自动登录和自动远程执行命令。但当不能使用密钥验证的时候,我们就没有办法了。所以,这时候只要知道对方机器的账号和密码就可以通过expect脚本实现登录和远程命令。

使用之前先安装 expect 软件

[root@liuhongwei-01 ~]# yum install -y expect

 20.28 expect脚本远程登录

自动远程登录,登陆后不退出

首先编写脚本

[root@liuhongwei-01 shell]# vim ex1.sh

#!/usr/bin/expect
set host "192.168.93.128"
set passwd "xxxxxx"
spawn ssh root@$host
expect {
"yes/no" { send "yes\r"; exp_continue}
"assword:" { send "$passwd\r" }
}
interact

然后给脚本加上执行权限 a+x

[root@liuhongwei-01 shell]# ./ex1.sh
-bash: ./ex1.sh: 权限不够
[root@liuhongwei-01 shell]# chmod a+x ex1.sh
[root@liuhongwei-01 shell]# ./ex1.sh
spawn ssh root@192.168.93.128
The authenticity of host '192.168.93.128 (192.168.93.128)' can't be established.
ECDSA key fingerprint is 51:1c:64:b5:38:a5:ef:75:d9:a3:17:c6:fc:b2:b1:dd.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.93.128' (ECDSA) to the list of known hosts.
root@192.168.93.128's password: 
Last login: Thu Aug  2 09:34:39 2018 from 192.168.93.1
[root@hongwei-02 ~]# 

20.29 expect脚本远程执行命令

首先还是编写脚本

[root@liuhongwei-01 shell]# vim ex2.sh

#!/usr/bin/expect
set user "root"
set passwd "xxxx"
spawn ssh $user@192.168.93.128

expect {
"yes/no" { send "yes\r"; exp_continue}
"password:" { send "$passwd\r" }
}
expect "]*"     这一个命令是遇到]* *表示通配,遇到这样的符号我们就执行下面的操作
send "touch /tmp/12.txt\r"    \r表示回车
expect "]*"
send "echo 1212 > /tmp/12.txt\r"
expect "]*"
send "exit\r"
~                

给脚本加上执行权限

[root@liuhongwei-01 shell]# chmod a+x ex2.sh

执行这个脚本

[root@liuhongwei-01 shell]# ./ex2.sh
spawn ssh root@192.168.93.128
root@192.168.93.128's password: 
Last login: Thu Aug  2 09:49:23 2018 from 192.168.93.129
[root@hongwei-02 ~]# touch /tmp/12.txt
[root@hongwei-02 ~]# echo 1212 > /tmp/12.txt
[root@hongwei-02 ~]# [root@liuhongwei-01 shell]# 

我们进入到128的机器,然后执行二条命令并退出,回到128机器上看看有没有刚才创建的文件

[root@hongwei-02 ~]# ls /tmp/
aming.sock  db1.sql  hsperfdata_root  keepalived.conf  mysql.sock  php-fcgi.sock  test.com.log  test.sql  zrlog.sql
[root@hongwei-02 ~]# date
2018年 08月 02日 星期四 09:45:23 CST
[root@hongwei-02 ~]# ls -l /tmp/
总用量 4
-rw-r--r-- 1 root  root  5 8月   2 09:50 12.txt
srw-rw-rw- 1 root  root  0 8月   2 09:31 aming.sock
srwxrwxrwx 1 mysql mysql 0 8月   2 09:31 mysql.sock
srw-rw-rw- 1 root  root  0 8月   2 09:31 php-fcgi.sock
[root@hongwei-02 ~]# cat /tmp/12.txt
1212

20.30 expect脚本传递参数

expect也是可以传递参数,想shell的$1 $2,相当于内置变量

还是编写脚本

[root@liuhongwei-01 shell]# vim ex3.sh

#!/usr/bin/expect

set user [lindex $argv 0]    第一个参数
set host [lindex $argv 1]    第二个参数
set passwd "xxxxx"
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@liuhongwei-01 shell]# chmod a+x ex3.sh

然后执行脚本

[root@liuhongwei-01 shell]# ./ex3.sh root 192.168.93.128 ls
spawn ssh root@192.168.93.128
root@192.168.93.128's password: 
Last login: Thu Aug  2 09:50:19 2018 from 192.168.93.129
[root@hongwei-02 ~]# ls
1.txt  aming.txt  anaconda-ks.cfg  log  logs  php-7.1.6.tar.bz2  temp  zabbix-release-3.2-1.el7.noarch.rpm
[root@hongwei-02 ~]# [root@liuhongwei-01 shell]# 

执行的时候要加上 用户root ip 和要执行的命令,也就是上面所说的第一个参数 root 第二个参数 ip 第三个参数要执行的命令ls、

如果想要执行多条命令如下:

[root@hongwei-02 ~]# [root@liuhongwei-01 shell]# ./ex3.sh root 192.168.93.128 "ls;w;netstat -lntp"
spawn ssh root@192.168.93.128
root@192.168.93.128's password: 
Last login: Thu Aug  2 09:58:34 2018 from 192.168.93.129
[root@hongwei-02 ~]# ls;w;netstat -lntp
1.txt  aming.txt  anaconda-ks.cfg  log  logs  php-7.1.6.tar.bz2  temp  zabbix-release-3.2-1.el7.noarch.rpm
 10:00:31 up 30 min,  2 users,  load average: 0.00, 0.01, 0.08
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
root     pts/0    192.168.93.1     09:34    9:03   0.02s  0.02s -bash
root     pts/1    192.168.93.129   10:00    0.00s  0.06s  0.04s w
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:111             0.0.0.0:*               LISTEN      752/rpcbind         
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      2051/nginx: master  
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      985/sshd            
tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN      2099/master         
tcp        0      0 0.0.0.0:443             0.0.0.0:*               LISTEN      2051/nginx: master  
tcp6       0      0 :::3306                 :::*                    LISTEN      2266/mysqld         
tcp6       0      0 :::111                  :::*                    LISTEN      752/rpcbind         
tcp6       0      0 :::22                   :::*                    LISTEN      985/sshd            
tcp6       0      0 ::1:25                  :::*                    LISTEN      2099/master         
[root@hongwei-02 ~]# [root@liuhongwei-01 shell]# 

20.31 expect脚本同步文件

编写脚本

[root@liuhongwei-01 shell]# vim ex4.sh

#!/usr/bin/expect
set passwd "xxxxx" 
spawn rsync -av root@192.168.93.128:/tmp/12.txt /tmp/  我们把远程机器的tmp目录的12.txt同步到本机的tmp目录下
expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
expect eof
[root@liuhongwei-01 shell]# chmod a+x ex4.sh

执行脚本

[root@liuhongwei-01 shell]# ./ex4.sh
spawn rsync -av root@192.168.93.128:/tmp/12.txt /tmp/
root@192.168.93.128's password: 
receiving incremental file list
12.txt

sent 43 bytes  received 96 bytes  92.67 bytes/sec
total size is 5  speedup is 0.04
[root@liuhongwei-01 shell]# 

看一下本机的tmp目录下的12.txt

[root@liuhongwei-01 shell]# cat /tmp/12.txt
1212
[root@liuhongwei-01 shell]# ls -l /tmp/12.txt
-rw-r--r-- 1 root root 5 8月   2 09:50 /tmp/12.txt

我们把脚本中最后的expect eof注释掉的话,就是还没有同步就直接退出来了

spawn rsync -av root@192.168.93.128:/tmp/12.txt /tmp/
expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
#expect eof
[root@liuhongwei-01 shell]# ./ex4.sh
spawn rsync -av root@192.168.93.128:/tmp/12.txt /tmp/
root@192.168.93.128's password: [root@liuhongwei-01 shell]# 

20.32 expect脚本指定host和要同步的文件

编写脚本

[root@liuhongwei-01 shell]# vim ex5.sh

#!/usr/bin/expect
set passwd "w撒大声地6"
set host [lindex $argv 0]   第一个参数是host
set file [lindex $argv 1]   第二个参数是file
spawn rsync -av $file root@$host:$file  这个file是主机到对方机器,路径要写绝对路径
expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
expect eof
[root@liuhongwei-01 shell]# chmod a+x ex5.sh

执行脚本前我们创建一个1234文件,然后看一下执行结果

[root@liuhongwei-01 shell]# ls /tmp/
12.txt      hsperfdata_root        php-fcgi.sock                                                          zhangsan
aminglinux  keepalived+nginx.conf  systemd-private-b066e0862e624a66895ce4cf3f270aa0-httpd.service-xqI3bJ
aming.sock  mysql.sock             yangying
[root@liuhongwei-01 shell]# touch /tmp/1234.txt
[root@liuhongwei-01 shell]# ls /tmp/
1234.txt    aming.sock             mysql.sock                                                             yangying
12.txt      hsperfdata_root        php-fcgi.sock                                                          zhangsan
aminglinux  keepalived+nginx.conf  systemd-private-b066e0862e624a66895ce4cf3f270aa0-httpd.service-xqI3bJ
[root@liuhongwei-01 shell]# ./ex5.sh 192.168.93.128 "/tmp/1234.txt"
spawn rsync -av /tmp/1234.txt root@192.168.93.128:/tmp/1234.txt
root@192.168.93.128's password: 
sending incremental file list
1234.txt

sent 90 bytes  received 35 bytes  83.33 bytes/sec
total size is 0  speedup is 0.00

看一下远程机器有没有

[root@liuhongwei-01 shell]# ./ex1.sh
spawn ssh root@192.168.93.128
root@192.168.93.128's password: 
Last failed login: Thu Aug  2 10:07:47 CST 2018 from 192.168.93.129 on ssh:notty
There were 2 failed login attempts since the last successful login.
Last login: Thu Aug  2 10:00:31 2018 from 192.168.93.129
[root@hongwei-02 ~]# ls /tmp
1234.txt  12.txt  aming.sock  mysql.sock  php-fcgi.sock
[root@hongwei-02 ~]# 

20.33 构建文件分发系统

c772a24954dc8d1e95d31cdfcc3daedac57.jpg

首先定义rsync.expect脚本内容:

[root@hongwei-02 ~]# vim rsync.expect

#!/usr/bin/expect
set passwd "xxxxx"
set host [lindex $argv 0]
set file [lindex $argv 1]
spawn rsync -av --files-from=$file / root@$host:/ 这个file定义的就是list.txt而不是一个文件
expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
expect eof

然后再定义一个list.txt

vim /tmp/list.txt

/tmp/12.txt
/root/shell/1.sh
/tmp/1234.txt

这个文件就是同步的文件,必须保证文件路径对方机器也有,文件不需要保证,但是我们可以在rsync.expect文件中加上R选项会自动帮你创建。

set host [lindex $argv 0]
set file [lindex $argv 1]
spawn rsync -avR --files-from=$file / root@$host:/
expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
expect eof

然后还需要加上一个ip.txt

[root@hongwei-02 ~]# vim /tmp/ip.txt

192.168.93.128
127.0.0.1

做这个实验的时候,需要两台机器的密码都是一样的。但是可以使用秘钥认证

然后在编写一个rsync的shell脚本

[root@liuhongwei-01 shell]# vim rsync.sh

#!/bin/bash
for ip in `cat /tmp/ip.list`
do
    echo $ip
    ./rsync.expect $ip /tmp/list.txt
done

然后要给rsync.expect执行权限

[root@liuhongwei-01 shell]# chmod a+x rsync.expect

然后执行rsync.sh脚本

[root@liuhongwei-01 shell]# sh -x rsync.sh
++ cat /tmp/ip.txt
+ for ip in '`cat /tmp/ip.txt`'
+ echo 192.168.93.128
192.168.93.128
+ ./rsync.expect 192.168.93.128 /tmp/list.txt
spawn rsync -avR --files-from=/tmp/list.txt / root@192.168.93.128:/
root@192.168.93.128's password: 
building file list ... done
root/
root/shell/
root/shell/1.sh
tmp/

sent 274 bytes  received 44 bytes  212.00 bytes/sec
total size is 64  speedup is 0.20
+ for ip in '`cat /tmp/ip.txt`'
+ echo 127.0.0.1
127.0.0.1
+ ./rsync.expect 127.0.0.1 /tmp/list.txt
spawn rsync -avR --files-from=/tmp/list.txt / root@127.0.0.1:/
The authenticity of host '127.0.0.1 (127.0.0.1)' can't be established.
ECDSA key fingerprint is 51:1c:64:b5:38:a5:ef:75:d9:a3:17:c6:fc:b2:b1:dd.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '127.0.0.1' (ECDSA) to the list of known hosts.
root@127.0.0.1's password: [root@liuhongwei-01 shell]# 

然后我回到2机器上看看有没有同步成功

[root@hongwei-02 ~]# ls -l /root/shell/1.sh 
-rwxr-xr-x 1 root root 59 7月  27 21:22 /root/shell/1.sh
[root@liuhongwei-01 shell]# ls -l /root/shell/1.sh 
-rwxr-xr-x 1 root root 59 7月  27 21:22 /root/shell/1.sh

20.34 批量远程执行命令

首先编写脚本

[root@liuhongwei-01 shell]# vim exe.expect

#!/usr/bin/expect
set host [lindex $argv 0]
set passwd "sdsd"
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@liuhongwei-01 shell]# chmod a+x !$
chmod a+x exe.expect
[root@liuhongwei-01 shell]# 

然后在编写exe的shell脚本,就是for循环

[root@hongwei-02 ~]# [root@liuhongwei-01 shell]# vim exe.sh

#!/bin/bash
for ip in `cat /tmp/ip.txt`
do
    ./exe.expect $ip "w;ls /tmp"
done

然后执行

[root@liuhongwei-01 shell]# sh exe.sh
spawn ssh root@192.168.93.128
root@192.168.93.128's password: 
Last login: Thu Aug  2 11:00:19 2018 from 192.168.93.129
[root@hongwei-02 ~]# w;ls /tmp
 11:00:46 up  1:30,  2 users,  load average: 0.00, 0.01, 0.05
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
root     pts/0    192.168.93.1     09:34   10:54   0.10s  0.10s -bash
root     pts/1    192.168.93.129   11:00    0.00s  0.01s  0.01s w
1234.txt  12.txt  aming.sock  ip.txt  list.txt  mysql.sock  php-fcgi.sock
[root@hongwei-02 ~]# [root@liuhongwei-01 shell]# 


 

expect的核心是spawn expect send set

spawn:调用要执行的命令
expect:等待命令提示信息的出现,也就是捕捉用户输入的提示:
send:发送需要交互的值,替代了用户手动输入内容
set:设置变量值
interact:执行完成后保持交互状态,把控制权交给控制台,这个时候就可以手工操作了。如果没有这一句登录完成后会退出,而不是留在远程终端上。
expect eof:这个一定要加,与 spawn 对应表示捕获终端输出信息终止,类似于 if....endif
expect 脚本必须以 interact 或 expect eof 结束,执行自动化任务通常 expect eof 就够了。

2. 设置 timeout

设置 expect 永不超时
set timeout -1

设置 expect 300 秒超时,如果超过 300 没有 expect 内容出现,则推出
set timeout 300

转载于:https://my.oschina.net/u/3851487/blog/1921334

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值