一、什么是分发系统?(循序渐进)
服务上线,这个词应该不陌生,公司内部一般都会有很多服务器,随着业务的不断发展,我们需要不断的去调整服务器的各项配置来适配现在的需求,但是server很多不可能一台一台的去修改,浪费人工和时间,这时候我们需要一个系统,这个系统可以帮助我们把更新的配置更新到每台服务器。
二、远程登录
2.1 环境需求
2.2 模板机配置
[root@zhdy-03 ~]# yum install -y expect
2.3 自动远程登录,执行命令
vim main.expect
#! /usr/bin/expect
set host "192.168.59.132"
set passwd "123456"
spawn ssh [email protected]$host
expect {
"yes/no" { send "yes\r"; exp_continue}
"assword:" { send "$passwd\r" }
}
interact
关于expect核心语法,也许会有疑问,如下图:
当遇到如上第一次连接需要确认的时候,直接yes \r是回车的意思,然后继续,再次输入密码,这个地方的密码就是上面定义的对方server的密码。
注意以上格式,和我们正常使用的shell是不一样的语法!
2.4 授权
[[email protected]-03 sbin]# chmod a+x main.expect
2.5 连接运行脚本
[[email protected]-03 sbin]# ./main.expect
spawn ssh [email protected]192.168.59.132
The authenticity of host '192.168.59.132 (192.168.59.132)' can't be established.
ECDSA key fingerprint is d3:ff:16:8c:ae:78:c5:54:01:35:01:e4:b6:34:cc:f7.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.59.132' (ECDSA) to the list of known hosts.
[email protected]192.168.59.132's password:
Last login: Wed Sep 20 17:13:47 2017 from 192.168.59.1
[[email protected]-04 ~]#
这样就轻松的连接到了对方的server。
三、脚本远程执行命令 (自动远程登录后,执行命令并退出 )
3.1 在理解刚刚脚本的基础上,再次提升脚本的功能:
vim main2.expect
#!/usr/bin/expect
set user "root"
set passwd "123456"
spawn ssh $user@192.168.59.132
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"
[[email protected]-03 sbin]# chmod a+x main2.expect
3.2 脚本分析:
当我们执行成功后,做了一些动作, 创建了touch /tmp/12.txt一个文件,并且在文件内写了一个数据,然后退出远程server。
3.3 执行效果如下:
[[email protected]-03 sbin]# ./main2.expect
spawn ssh [email protected]192.168.59.132
[email protected]192.168.59.132's password:
Last failed login: Wed Sep 20 17:42:55 CST 2017 from 192.168.59.131 on ssh:notty
There was 1 failed login attempt since the last successful login.
Last login: Wed Sep 20 17:27:05 2017 from 192.168.59.131
[[email protected]-04 ~]# touch /tmp/12.txt
[[email protected]-04 ~]# echo 1212 > /tmp/12.txt
[[email protected]-04 ~]# [[email protected] sbin]#
最后还是退回到了咱们这台机器。
3.4 检查
我们登录到线上的server去查看下是否已经创建了文件呢?
[root@zhdy-03 sbin]# ./main.expect
spawn ssh root@192.168.59.132
root@192.168.59.132's password:
Last login: Wed Sep 20 17:43:27 2017 from 192.168.59.131
[root@zhdy-04 ~]# ls /tmp/
12.txt sh-thd-1505201881
[root@zhdy-04 tmp]# cat 12.txt
1212
四、脚本传递参数
4.1 脚本参数设置
vim main3.expect
#!/usr/bin/expect
set user [lindex $argv 0]
set host [lindex $argv 1]
set passwd "123456"
set cm [lindex $argv 2]
spawn ssh [email protected]$host
expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
expect "]*"
send "$cm\r"
expect "]*"
send "exit\r"
脚本中的 $argv 0 或者 $argv 1 就是所谓的执行脚本时候所输入的第一个第二个参数。
4.2 授权
[[email protected]-03 sbin]# chmod a+x main3.expect
4.3 执行测试
[[email protected] sbin]# ./main3.expect root 192.168.59.132 ls
spawn ssh [email protected]192.168.59.132
[email protected]192.168.59.132's password:
Last login: Wed Sep 20 17:45:21 2017 from 192.168.59.131
[[email protected] ~]# ls
anaconda-ks.cfg sendEmail-v1.56 zabbix-release-3.2-1.el7.noarch.rpm
awk sendEmail-v1.56.tar.gz zabbix-release-3.2-1.el7.noarch.rpm.1
执行后不难发现,第一个参数就是user,第二个是主机host,第三个就是需要执行的命令。
补充:
脚本在执行的时候会执行远程命令默认是10秒钟,如何让他不限时间呢?
#!/usr/bin/expect
set user [lindex $argv 0]
set host [lindex $argv 1]
set passwd "123456"
set cm [lindex $argv 2]
spawn ssh [email protected]$host
expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
expect "]*"
send "$cm\r"
set timeout -1
expect "]*"
send "exit\r"
也就是说我们只需要添加set timeout -1即可! 当然也可以设置不同的秒,set timeout 5 意味着5秒就自动退出
当然也可以同时执行多个命令:
[root@zhdy-03 sbin]# ./main3.expect root 192.168.59.132 "ls;w;vmstat 1 2"
spawn ssh root@192.168.59.132
root@192.168.59.132's password:
Last login: Wed Sep 20 18:01:28 2017 from 192.168.59.131
[root@zhdy-04 ~]# ls;w;vmstat 1 2
anaconda-ks.cfg sendEmail-v1.56 zabbix-release-3.2-1.el7.noarch.rpm
awk sendEmail-v1.56.tar.gz zabbix-release-3.2-1.el7.noarch.rpm.1
18:04:07 up 51 min, 2 users, load average: 0.01, 0.06, 0.06
USER TTY FROM [email protected] IDLE JCPU PCPU WHAT
root pts/0 192.168.59.1 17:13 37:59 0.07s 0.07s -bash
root pts/1 192.168.59.131 18:04 0.00s 0.01s 0.00s w
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 206580 876 200056 0 0 54 49 83 187 0 0 98 1 0
0 0 0 206580 876 200080 0 0 0 0 53 114 0 0 100 0 0
[root@zhdy-04 ~]# [root@zhdy-03 sbin]#
如上不难发现,已经正常的登录,并且执行了我们所需要的命令参数。
五、自动同步文件
5.1 配置脚本
核心命令,就是用的rsync服务。
#!/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
5.2 授权并测试
[root@zhdy-03 sbin]# chmod a+x main4.expect
[root@zhdy-03 sbin]# ./main4.expect
spawn rsync -av root@192.168.59.132:/tmp/12.txt /tmp/
root@192.168.59.132's password:
receiving incremental file list
12.txt
sent 36 bytes received 84 bytes 80.00 bytes/sec
total size is 5 speedup is 0.04
如上可以看出 已经成功的同步了文件。
expect eof 脚本中,如果我们不加此语句,一旦登录成功就退出。
六、指定host和要同步的文件
6.1 脚本配置
vim main5.expect
#!/usr/bin/expect
set passwd "123456"
set host [lindex $argv 0]
set file [lindex $argv 1]
spawn rsync -av $file [email protected]$host:$file
expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
expect eof
脚本主要意思是:推送一个本地文件到远程服务器。
6.2 授权
[[email protected]-03 sbin]# chmod a+x main5.expect
我现在尝试吧我本地的一个文件推送到服务器:文件内容如下:
[[email protected] sbin]# cat /tmp/users.txt
username: user_9 password: 1zg^NIx7on
username: user_5 password: e21oHjeYg=
username: user_6 password: e21oHjeYg=
username: user_7 password: e21oHjeYg=
username: user_8 password: e21oHjeYg=
username: user_5 password: gNR0o{1qjw
username: user_6 password: Pam1lxsN6[
username: user_7 password: 6hd5p^XgwM
username: user_8 password: kvcoyJ5_G0
username: user_5 password: is0wb*SNj7
username: user_6 password: BEgg89qgz<
username: user_7 password: Nxvt8-xGw8
username: user_8 password: 6mpbk5sDS-
6.3 执行
[root@zhdy-03 sbin]# ./main5.expect 192.168.59.132 "/tmp/users.txt"
spawn rsync -av /tmp/users.txt root@192.168.59.132:/tmp/users.txt
root@192.168.59.132's password:
sending incremental file list
users.txt
sent 571 bytes received 31 bytes 1204.00 bytes/sec
total size is 494 speedup is 0.82
6.4 去远程服务器上查看
[[email protected] ~]# cat /tmp/users.txt
username: user_9 password: 1zg^NIx7on
username: user_5 password: e21oHjeYg=
username: user_6 password: e21oHjeYg=
username: user_7 password: e21oHjeYg=
username: user_8 password: e21oHjeYg=
username: user_5 password: gNR0o{1qjw
username: user_6 password: Pam1lxsN6[
username: user_7 password: 6hd5p^XgwM
username: user_8 password: kvcoyJ5_G0
username: user_5 password: is0wb*SNj7
username: user_6 password: BEgg89qgz<
username: user_7 password: Nxvt8-xGw8
username: user_8 password: 6mpbk5sDS-
已经成功推送!!!
但是这只是开始,一般我们推送一个软件或者上线一个服务肯定不是一个文件就可以的。所以我们需要的是大量的文件子目录+脚本推送。
七、文件分发系统实现
7.1 需求背景
对于大公司而言,肯定时不时会有网站或者配置文件更新,而且使用的机器肯定也是好多台,少则几台,多则几十甚至上百台。所以,自动同步文件是至关重要的。
实现思路:
首先要有一台模板机器,把要分发的文件准备好,然后只要使用expect脚本批量把需要同步的文件分发到目标机器即可。
核心命令:
rsync -av --files-from=list.txt / [email protected]t:/
7.2 脚本配置
#!/usr/bin/expect
set passwd "123456"
set host [lindex $argv 0]
set file [lindex $argv 1]
spawn rsync -avR --files-from=$file / [email protected]$host:/
expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
expect eof
rsync -av –files-from=$file / [email protected]$host:/:上传文件的列表是$file,我们需要在list当中去定义 哪些目录或文件是我们需要同步更新上线的。
授权:
[[email protected]-03 sbin]# chmod a+x rsync.expect
[[email protected]03 sbin]# vim /tmp/list.txt
/tmp/12.txt
/usr/local/sbin/23.sh
/tmp/disk.txt
假如我们需要同步如上3个文件,前提是一定要保证对方的server一定也要有这个目录,例如: /tmp/ /user/local/sbin/ /tmp/, 不然同步会出错。(如上脚本中我们添加了 rsync -avR R就是自动创建级联的目录。)
一般我们代码上线肯定不是针对一台机器来操作的,所以我们也需要定义ip list
[[email protected]-03 sbin]# vim /tmp/ip.list
192.168.59.132
127.0.0.1
还有一个重要的前提就是:所有的机器必须要保证有着相同的密码。但是这样操作有点危险,一旦文档泄露就比较麻烦了。所以我们会选择针对需要同步的服务器进行密钥认证。一旦密钥认证后,如下脚本中的语句我们就可以省略:
"password:" { send "$passwd\r" }
7.3 创建一个rsync的shell
[[email protected] sbin]# vim rsync.sh
#!/bin/bash
for ip in `cat /tmp/ip.list`
do
echo $ip
./rsync.expect $ip /tmp/list.txt
done
此脚本的目的就是遍历所有的server和list中的文件可以同步到每台服务器。
7.4 执行测试
[[email protected] sbin]# sh -x rsync.sh
++ cat /tmp/ip.list
+ for ip in '`cat /tmp/ip.list`'
+ echo 192.168.59.132
192.168.59.132
+ ./rsync.expect 192.168.59.132 /tmp/list.txt
spawn rsync -avR --files-from=/tmp/list.txt / [email protected]:/
[email protected]'s password:
building file list ... done
home/
home/user_00/
home/user_00/.bashrc
tmp/
usr/local/
usr/local/sbin/
usr/local/sbin/1.txt
sent 553 bytes received 65 bytes 1236.00 bytes/sec
total size is 250 speedup is 0.40
+ for ip in '`cat /tmp/ip.list`'
+ 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 / [email protected]:/
[email protected]'s password:
building file list ... done
sent 207 bytes received 12 bytes 438.00 bytes/sec
total size is 250 speedup is 1.14
八、批量远程执行命令
有时候当我们传输同步完毕之后,可能需要重启一下nginx服务,或者mysql服务,这样就用到了远程执行命令。
8.1 脚本配置
vim exe.expect
#!/usr/bin/expect
set host [lindex $argv 0]
set passwd "123456"
set cm [lindex $argv 1]
spawn ssh [email protected]$host
expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
expect "]*"
send "$cm\r"
expect "]*"
send "exit\r"
set host [lindex $argv 0]:第一个参数
set cm [lindex $argv 1]:第二个参数
8.2 授权
[[email protected]-03 sbin]# chmod a+x exe.expect
8.3 定义exe的shell脚本
vim exe.sh
#!/bin/bash
for ip in `cat ip.list`
do
echo $ip
./exe.expect $ip "w;free -m;ls /tmp"
done
8.3 执行检测
[[email protected]03 sbin]# sh exe.sh
192.168.96.130
spawn ssh [email protected]192.168.96.130
Last login: Fri Sep 22 00:20:41 2017 from 192.168.96.1
_oo0oo_
088888880
88" . "88
(| -_- |)
0\ = /0
___/'---'\___
.' \\\\| |// '.
/ \\\\||| : |||//\\
/_ ||||| -:- |||||- \\
| | \\\\\\ - /// | |
| \_| ''\---/'' |_/ |
\ .-\__ '-' __/-. /
___'. .' /--.--\ '. .'___
."" '< '.___\_<|>_/___.' >' "".
| | : '- \'.;'\ _ /';.'/ - ' : | |
\ \ '_. \_ __\ /__ _/ .-' / /
====='-.____'.___ \_____/___.-'____.-'=====
'=---='
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
佛祖保佑 iii 永不死机
[[email protected]04 ~]# w;free -m;ls /tmp
01:11:44 up 53 min, 2 users, load average: 0.00, 0.01, 0.03
USER TTY FROM [email protected] IDLE JCPU PCPU WHAT
root pts/0 192.168.96.1 00:20 10:32 0.01s 0.01s -bash
root pts/1 192.168.96.129 01:11 0.00s 0.00s 0.00s w
total used free shared buff/cache available
Mem: 976 85 758 6 132 740
Swap: 2047 0 2047
systemd-private-0a7ea94bd4d44c118420e4eb27a12be4-vmtoolsd.service-dwg4H7
已经成功登陆到了定义的远程server,并且执行了相关的命令!