第二十章 Shell编程(下)

20.27 分发系统介绍

20.28 expect脚本远程登录

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

set 定义变量
spawn 执行命令
expect 使用expect语句进行交互
\r表示回车
exp_contunue表示继续
interact表示继续交互
expect eof表示停留远程机器上一会儿再退出

20.29 expect脚本远程执行命令

#!/usr/bin/expect
set user "root"
set passwd "123456"
spawn ssh [email protected]

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"

20.30 expect脚本传递参数

#!/usr/bin/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"

[lindex $argv 0]表示要输入的第一个参数 如此类推

当要输入参数里面有多个命令是需要用""双引号括起来并使用;分号分开

可以在命令行的后面增加set timeout 来指定命令的超时时间 -1为永远

20.31 expect脚本同步文件

#!/usr/bin/expect
set passwd "123456"
spawn rsync -av [email protected]:/tmp/12.txt /tmp/
expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
expect eof

20.32 expect脚本指定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
 

20.33 构建文件分发系统

[root@centos01 shell]# cat rsync.expect 
#!/usr/bin/expect
set passwd "123456"
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
[root@centos01 tmp]# cat ip.list 
192.168.93.128
[root@centos01 tmp]# cat list.txt 
/tmp/12.txt
/root/shell/qq.txt

20.34 批量远程执行命令

[root@centos01 tmp]# cat exe.expect 
#!/usr/bin/expect
set host [lindex $argv 0]
set passwd "123456"
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@centos01 tmp]# cat /tmp/ip.list 
192.168.93.128

课堂串讲

20.27 分发系统介绍
20.28 expect脚本远程登录
20.29 expect脚本远程执行命令
20.30 expect脚本传递参数

20.27 分发系统介绍

公司的网站本来已经建好了,当公司的业务越来l越大时候就会需要实时更新代码,由于后端服务器有很多台来跑web服务。此时为了快速更新代码就可以使用分发系统。其中开源的上线代码的软件有很多,git等等。这里我们使用shell来编写一个分发系统来上线代码。核心使用expect脚本语言,它可以实现远程执行命令,远程传输数据等操作。

  • 准备工作
    1.准备1台模版机器,里面是包含有最新的代码
    2.每台分发机器的IP地址和密码
    3.分发系统脚本
    由于分发系统的核心是使用expect,因此先实践几个例子来熟悉expect的语法命令

20.28 expect脚本远程登录

实例1.自动远程登录

expect脚本机器 kun05 192.168.80.104
被远程的机器 kun03 192.168.80.102

1.安装expect语言

1
[root@kun05 ~]# yum install -y expect

2.编辑脚本

1
2
[root@kun05 ~]# cd /usr/local/sbin/
[root@kun05 sbin]# vim expect1.exp

写入下面代码

1
2
3
4
5
6
7
8
9
10
11
12
#!/usr/bin/expect
#定义变量
set host "192.168.80.102"
set passwd "coco0769"
#执行命令
spawn ssh root@$host
#与远程机器交互 截取特定信息 发送变量
expect {
"yes/no" { send "yes\r";exp_continue }
"password:" { send "$passwd\r" }
}
interact

set 定义变量
spawn 执行命令
expect 使用expect语句进行交互
\r表示回车
exp_contunue表示继续
interact表示继续交互
expect eof表示停留远程机器上一会儿再退出

为了让远程登录时候出现提示,可以清空/root/.ssh/known_hosts目录

1
[root@kun05 ~]# > /root/.ssh/known_hosts

测试

1.添加执行权限

1
[root@kun05 sbin]# chmod a+x expect1.exp

2.执行脚本

1
2
3
4
5
6
7
8
9
10
[root@kun05 sbin]# ./expect1.exp
spawn ssh [email protected]
The authenticity of host '192.168.80.102 (192.168.80.102)' can't be established.
ECDSA key fingerprint is SHA256:4QK/8Tn8lZAitB2+3wJMBuONgHExXkOAzZpYPndYoPQ.
ECDSA key fingerprint is MD5:89:d5:7c:90:ff:d2:c6:1a:6e:f8:58:48:29:78:9a:f3.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.80.102' (ECDSA) to the list of known hosts.
[email protected]'s password:
Last login: Thu Jul 19 21:52:22 2018 from 192.168.80.104
[root@kun03 ~]#

已经成功登录kun03机器上

20.29 expect脚本远程执行命令

实例2.自动远程登录,并执行命令并退出

编辑脚本

1
[root@kun05 sbin]# vim expect2.exp

写入下面代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/usr/bin/expect
set user "root"
set host "192.168.80.102"
set passwd "coco0769"
spawn ssh $user@$host
expect {
"yes/no" {send "yes\r";exp_continue}
"password:" {send "$passwd\r"}
}
expect "]*"
send "touch /tmp/test.aa\r"
expect "]*"
send "echo 111 >/tmp/test.aa\r"
expect "]*"
send "exit\r"

测试

添加执行权限并执行脚本

1
2
3
4
5
6
7
[root@kun05 sbin]# chmod a+x expect2.exp
[root@kun05 sbin]# ./expect2.exp
spawn ssh [email protected]
[email protected]'s password:
Last login: Thu Jul 19 22:48:29 2018 from 192.168.80.104
[root@kun03 ~]# touch /tmp/test.aa
[root@kun03 ~]# echo 111 >/tmp/test.aa

进入kun03机器看看

1
2
3
4
[root@kun03 ~]# ll /tmp/test.aa
-rw-r--r-- 1 root root 4 7月  19 22:50 /tmp/test.aa
[root@kun03 ~]# cat  /tmp/test.aa
111

20.28 expect脚本传递参数

实例3.远程传递参数

编辑脚本

1
[root@kun05 sbin]# vim expect3.exp

写入下面代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/usr/bin/expect
set user [lindex $argv 0]
set host [lindex $argv 1]
set passwd "coco0769"
set cmd [lindex $argv 2]
spawn ssh $user@$host
expect {
"yes/no" {send "yes\r"}
"password:" {send "$passwd\r"}
}
expect "]*"
send "$cmd\r"
expect "]*"
send "exit\r"

[lindex $argv 0]表示要输入的第一个参数 如此类推

测试

添加执行权限并执行脚本

1
2
3
4
5
6
7
8
9
10
11
12
[root@kun05 sbin]# chmod a+x expect3.exp
[root@kun05 sbin]# ./expect3.exp root 192.168.80.102 "ls;w"
spawn ssh [email protected]
[email protected]'s password:
Last login: Thu Jul 19 22:52:09 2018 from 192.168.80.1
[root@kun03 ~]# ls;w
anaconda-ks.cfg  ip_forwarx~  ip_forwarz~  logs     temp
ip_forward~      ip_forwary~  log          sim.pid  zabbix-release-3.4-2.el7.noarch.rpm
23:45:34 up  2:02,  2 users,  load average: 0.01, 0.03, 0.05
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
root     pts/0    192.168.80.1     22:52    7:58   0.01s  0.01s -bash
root     pts/1    192.168.80.104   23:45    0.00s  0.00s  0.00s w

当要输入参数里面有多个命令是需要用""双引号括起来并使用;分号分开

可以在命令行的后面增加set timeout 来指定命令的超时时间 -1为永远

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/usr/bin/expect
set user [lindex $argv 0]
set host [lindex $argv 1]
set passwd "coco0769"
set cmd [lindex $argv 2]
spawn ssh $user@$host
expect {
"yes/no" {send "yes\r"}
"password:" {send "$passwd\r"}
}
expect "]*"
send "$cmd\r"
set timeout -1
expect "]*"
send "exit\r"

测试

输入vmstat命令

1
2
3
4
5
6
7
8
9
10
11
12
[root@kun03 ~]# [root@kun05 sbin]# ./expect3.exp "root" 192.168.80.102 "vmstat 1"
spawn ssh [email protected]
[email protected]'s password:
Last login: Fri Jul 20 21:42:43 2018 from 192.168.80.104
[root@kun03 ~]# 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
2  0      0 167852   2108 168580    0    0    35     3   85  113  0  0 99  0  0
0  0      0 167480   2108 168592    0    0     0     0   91  113  0  1 99  0  0
0  0      0 167480   2108 168592    0    0     0     0  104  119  0  0 100  0  0
0  0      0 167480   2108 168592    0    0     0     0   79   96  0  1 99  0  0
0  0      0 167480   2108 168592    0    0     0     0   89  106  0  0 100  0  0

现在是不断地执行vmstat命令

20.31 expect脚本同步文件
20.32 expect脚本指定host和要同步的文件
20.33 构建文件分发系统
20.34 批量远程执行命令

20.31 expect脚本同步文件

实例4.自动同步文件

编辑脚本

1
[root@kun05 sbin]# vim expect4.exp

写入下面代码

1
2
3
4
5
6
7
8
#!/usr/bin/expect
set passwd "coco0769"
spawn rsync -av [email protected]:/tmp/test.aa /tmp/
expect {
"yes/no" {send "yes\r"}
"password:" {send "$passwd\r"}
}
expect eof

测试

添加执行权限并执行脚本

1
2
3
4
5
6
7
8
9
10
11
12
[root@kun05 sbin]# chmod a+x expect4.exp
[root@kun05 sbin]# ./expect4.exp
spawn rsync -av [email protected]:/tmp/test.aa /tmp/
[email protected]'s password:
receiving incremental file list
test.aa

sent 43 bytes  received 97 bytes  280.00 bytes/sec
total size is 4  speedup is 0.03

[root@kun05 sbin]# ll /tmp/test.aa
-rw-r--r-- 1 root root 4 7月  19 22:50 /tmp/test.aa

已经把192.168.80.102的test.aa文件自动同步过来本机了

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

实例5.指定host和同步单个文件

编辑脚本

1
[root@kun05 sbin]# vim expect5.exp

写入下面代码

1
2
3
4
5
6
7
8
9
10
#!/usr/bin/expect
set passwd "coco0769"
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

测试

添加执行权限并执行脚本

1
2
3
4
5
6
7
8
9
[root@kun05 sbin]# chmod a+x expect5.exp
[root@kun05 sbin]# ./expect5.exp 192.168.80.102 /tmp/test
spawn rsync -av /tmp/test [email protected]:/tmp/test
[email protected]'s password:
sending incremental file list
test

sent 85 bytes  received 35 bytes  240.00 bytes/sec
total size is 0  speedup is 0.00

20.33 构建文件分发系统

分发系统中首先用expect编写远程同步脚本 并指定文件列表目标IP列表 然后使用shell脚本调用expect来同步文件。
这里每台机器必须使用同样的密码才可以同步,也可以让机器之前使用密钥登录。还有让每台机器都安装上rsync
其核心命令为rsync -av --files-from=list.txt / root@host:/

1.编辑expect脚本

1
[root@kun05 sbin]# vim rsync.exp

写入下面代码

1
2
3
4
5
6
7
8
9
10
11
#!/usr/bin/expect
set passwd "coco0769"
set host [lindex $argv 0]
set file [lindex $argv 1]
#--file-from指定文件列表路径 -R表示同步时目标会级联创建目录
spawn rsync -avR --files-from=$file / root@$host:/
expect {
"yes/no" {send "yes\r"}
"password:" {send $passwd\r}
}
expect eof

2.创建ip.list 同步机器的IP列表

1
2
3
4
[root@kun05 sbin]# vim /tmp/ip.list

192.168.80.102
192.168.80.103

3.创建file.list 需要同步文件的列表

1
2
3
4
[root@kun05 sbin]# vim /tmp/file.list

/tmp/test
/tmp/test.aa

4.创建 rsync.sh 脚本

1
[root@kun05 sbin]# vim rsync.sh

写入下面代码

1
2
3
4
5
#!/bin/bash
for i in `cat /tmp/ip.list`
do
        ./rsync.exp $i /tmp/file.list
done

测试

添加执行权限并执行脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[root@kun05 sbin]# chmod a+x rsync.exp
[root@kun05 sbin]# sh +x rsync.sh
spawn rsync -avR --files-from=/tmp/file.list / [email protected]:/
[email protected]'s password:
building file list ... done
tmp/
tmp/test
tmp/test.aa

sent 185 bytes  received 57 bytes  161.33 bytes/sec
total size is 11  speedup is 0.05
spawn rsync -avR --files-from=/tmp/file.list / [email protected]:/
[email protected]'s password:
building file list ... done
tmp/
tmp/test
tmp/test.aa

sent 185 bytes  received 57 bytes  484.00 bytes/sec
total size is 11  speedup is 0.05

20.34 批量远程执行命令

当同步完代码后有可能需要批量地重启服务,因此还需要批量远程执行命令,类似于自动化。
这里是用expect编写执行命令的脚本并用shell脚本来批量调用它。

1.编辑expect脚本

1
[root@kun05 sbin]# vim exe.exp

写入下面代码

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/usr/bin/expect
set passwd "coco0769"
set host [lindex $argv 0]
set cmd [lindex $argv 1]
spawn ssh root@$host
expect {
"yes/no" {send "yes\r"}
"password:" {send "$passwd\r"}
}
expect "]*"
send "$cmd\r"
expect "]*"
send "exit\r"

2.编写shell脚本

1
[root@kun05 sbin]# vim exe.sh

写入下面代码

1
2
3
4
5
6
#!/bin/bash
for i in `cat /tmp/ip.list`
do
        echo $i
        ./exe.exp $i "service nginx restart"
done

测试

添加执行权限并执行脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@kun05 sbin]# chmod a+x exe.exp
[root@kun05 sbin]# sh exe.sh
192.168.80.102
spawn ssh [email protected]
[email protected]'s password:
Last login: Fri Jul 20 23:40:28 2018 from 192.168.80.104
[root@kun03 ~]# service nginx restart
Restarting nginx (via systemctl):                          [  确定  ]
192.168.80.103
spawn ssh [email protected]
[email protected]'s password:
Last login: Fri Jul 20 23:38:46 2018 from 192.168.80.104
[root@kun04 ~]# service nginx restart
Restarting nginx (via systemctl):                          [  确定  ]

这里kun03和kun04机器都执行了service nginx restart命令

猜你喜欢

转载自blog.csdn.net/weixin_37817498/article/details/83474253