Name | Version |
---|---|
Centos 7 | 3.10.0-693.el7.x86_64 #1 SMP Tue Aug 22 21:09:27 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux |
expect | expect-5.45-14.el7_1.x86_64 |
分发系统介绍
上线:就是开发的代码发布到线上环境上去。
规范代码上线,使用分发系统(上线的shell脚本)expect(也是一种脚本语言,和shell类似),可以用它实现传输文件远程执行命令,不需输入密码;准备一台模板机器作为准备上线的代码,待发布的所有机器需要知道IP地址和待发布机器用户和密码。使用expect脚本借助rsync把代码推送到待上线机器上去,可以用expect登录这些机器去执行一些命令。
expect脚本远程登录
检查是否安装了expect,由于之前用户密码有安装过makepassword就有了expect
[root@zyshanlinux-001 ~]# yum install -y expect
自动远程登录的expect脚本
[root@zyshanlinux-001 ~]# vi 1.expect
#! /usr/bin/expect
set host "192.168.106.130"
set passwd "目标机器的登录密码"
spawn ssh root@$host
expect {
"yes/no" { send "yes\r"; exp_continue}
"password:" { send "$passwd\r" }
}
interact
spawn ssh是远程连接,expect { }是核心语句,"yes/no" 和"password:"是截取目标机器的反馈信息;"yes/no"是首次登录才会出现的语句,发现这句,就把"yes\r"发送过去(代表选择yes和回车=\r), exp_continue继续;"password:"则是不是首次登录了,曾经登录过的,则把密码发送过去;interact代表停留在目标机器上,如果把interact改为expect eof则是停留在目标机器上1到2秒,2个都不写的话刚登录上去就马上退出来。
如何把曾经登录的记录清除,变成首次登录;把/root/.ssh/known_hosts文本下把内容全部清除就可以实现。
[root@zyshanlinux-001 ~]# ssh 192.168.106.130
root@192.168.106.130's password:
[root@zyshanlinux-001 ~]# vi /root/.ssh/known_hosts
192.168.106.130 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEF7hfCPEDqjB5YyJia4Sv7KxKwu9hPgLHToFvswJX5sCb94mK9E5/MXVeZlzi15swGXR6zHerxAzw5hwtyvpzQ=
192.168.43.223 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBCvqX9Y+H3Ngex45gxNgfSI6qzdhFSzNT9npJ1r5x087sNi2AGEhlFfE4HsuOIEGCijYFTzkxtV7WHsz/2LGN2I=
执行1.expect脚本登录目标机器,首先要给1.expect执行权限;执行脚本./1.expect,成功登录目标机器。
[root@zyshanlinux-001 ~]# chmod a+x 1.expect
[root@zyshanlinux-001 ~]# ./1.expect
spawn ssh root@192.168.106.130
root@192.168.106.130's password:
Last login: Sat Jul 28 12:15:28 2018 from 192.168.106.1
[root@zyshanlinux-02 ~]#
expect脚本远程执行命令
自动远程登录后,执行命令并退出
[root@zyshanlinux-02 ~]# logout
Connection to 192.168.106.130 closed.
[root@zyshanlinux-001 ~]# vi 2.expect
#!/usr/bin/expect
set user "root"
set passwd "目标机器的登录密码"
spawn ssh $user@192.168.106.130
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"
进入目标机器后,会出现[root@zyshanlinux-02 ~]#或普通用户02 ~]$,所以expect "]*"就是通配出该字符,就执行命令,最后执行完命令,就exit退出。
给予2.expect执行权限,执行就可以看到在目标机器上创建文件并写入数据最后退出该机器。
[root@zyshanlinux-001 ~]# chmod a+x 2.expect
[root@zyshanlinux-001 ~]# ./2.expect
spawn ssh root@192.168.106.130
root@192.168.106.130's password:
Last login: Thu Aug 2 21:35:03 2018 from 192.168.106.128
[root@zyshanlinux-02 ~]# touch /tmp/12.txt
[root@zyshanlinux-02 ~]# echo 1212 > /tmp/12.txt
[root@zyshanlinux-02 ~]# [root@zyshanlinux-001 ~]#
[root@zyshanlinux-001 ~]# ./1.expect
spawn ssh root@192.168.106.130
root@192.168.106.130's password:
Last login: Thu Aug 2 21:46:55 2018 from 192.168.106.128
[root@zyshanlinux-02 ~]# ls -l /tmp/12.txt
-rw-r--r-- 1 root root 5 8月 2 21:46 /tmp/12.txt
[root@zyshanlinux-02 ~]# cat !$
cat /tmp/12.txt
1212
[root@zyshanlinux-02 ~]#
expect脚本传递参数
传递[lindex $argv 0]、[lindex $argv 1]和[lindex $argv 2]这三个参数,代表用户、IP和命令。
[root@zyshanlinux-001 ~]# vi 3.expect
#!/usr/bin/expect
set user [lindex $argv 0]
set host [lindex $argv 1]
set passwd "目标机器的登录密码"
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@zyshanlinux-001 ~]# chmod a+x 3.expect
[root@zyshanlinux-001 ~]# ./3.expect root 192.168.106.130 'ls -l'
spawn ssh root@192.168.106.130
root@192.168.106.130's password:
Last login: Thu Aug 2 22:00:38 2018 from 192.168.106.128
[root@zyshanlinux-02 ~]# ls -l
总用量 20
-rw-------. 1 root root 1418 5月 7 04:27 anaconda-ks.cfg
-rw-r--r-- 1 root root 13392 9月 14 2016 zabbix-release-3.2-1.el7.noarch.rpm
[root@zyshanlinux-02 ~]# [root@zyshanlinux-001 ~]# ./3.expect root 192.168.106.130 "ls -l;w"
spawn ssh root@192.168.106.130
root@192.168.106.130's password:
Last login: Thu Aug 2 22:01:03 2018 from 192.168.106.128
[root@zyshanlinux-02 ~]# ls -l;w
总用量 20
-rw-------. 1 root root 1418 5月 7 04:27 anaconda-ks.cfg
-rw-r--r-- 1 root root 13392 9月 14 2016 zabbix-release-3.2-1.el7.noarch.rpm
22:03:40 up 48 min, 1 user, load average: 0.03, 0.06, 0.06
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
root pts/0 192.168.106.128 22:03 0.00s 0.02s 0.01s w
[root@zyshanlinux-02 ~]# [root@zyshanlinux-001 ~]#
expect脚本同步文件
把目标机器的12.txt利用rsync同步到本机器来。
[root@zyshanlinux-001 ~]# vi 4.expect
#!/usr/bin/expect
set passwd "目标机器的登录密码"
spawn rsync -av root@192.168.106.130:/tmp/12.txt /tmp/
expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
expect eof
执行脚本
[root@zyshanlinux-001 ~]# chmod a+x 4.expect
[root@zyshanlinux-001 ~]# ./4.expect
spawn rsync -av root@192.168.106.130:/tmp/12.txt /tmp/
root@192.168.106.130's password:
receiving incremental file list
12.txt
sent 43 bytes received 97 bytes 93.33 bytes/sec
total size is 5 speedup is 0.04
[root@zyshanlinux-001 ~]# cat /tmp/12.txt
1212
expect脚本指定host和要同步的文件
设定超时为5秒命令set timeout 5,用命令vmstat 1可以测出超时时间为5秒,5秒后退出该命令,目标机器该命令也没有运行了,因为本地机器已经退出这个shell了所以目标机器的该命令也结束。
[root@zyshanlinux-001 ~]# vi 3.expect
#!/usr/bin/expect
set user [lindex $argv 0]
set host [lindex $argv 1]
set passwd "目标机器的登录密码"
set cm [lindex $argv 2]
spawn ssh $user@$host
expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
expect "]*"
send "$cm\r"
set timeout 5
expect "]*"
send "exit\r"
[root@zyshanlinux-001 ~]# ./3.expect root 192.168.106.130 'vmstat 1'
spawn ssh root@192.168.106.130
root@192.168.106.130's password:
Last login: Thu Aug 2 22:23:32 2018 from 192.168.106.128
[root@zyshanlinux-02 ~]# 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 1131600 2076 171300 0 0 37 36 119 142 0 1 99 0 0
0 0 0 1131108 2076 171340 0 0 0 7 137 150 1 1 98 0 0
0 0 0 1131108 2076 171340 0 0 0 6 147 152 0 1 99 0 0
0 0 0 1131108 2076 171344 0 0 0 6 132 146 0 0 100 0 0
0 0 0 1131076 2076 171344 0 0 0 6 140 151 0 2 98 0 0
把set timeout 5改为set timeout -1就会变为永久不超时。
[root@zyshanlinux-001 ~]# vi 3.expect
#!/usr/bin/expect
set user [lindex $argv 0]
set host [lindex $argv 1]
set passwd "目标机器的登录密码"
set cm [lindex $argv 2]
spawn ssh $user@$host
expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
expect "]*"
send "$cm\r"
set timeout -1
expect "]*"
send "exit\r"
[root@zyshanlinux-001 ~]# ./3.expect root 192.168.106.130 'vmstat 1'
spawn ssh root@192.168.106.130
root@192.168.106.130's password:
Last login: Thu Aug 2 22:23:56 2018 from 192.168.106.128
[root@zyshanlinux-02 ~]# 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 1131452 2076 171404 0 0 35 36 118 141 0 1 99 0 0
0 0 0 1131452 2076 171400 0 0 0 0 81 91 0 0 100 0 0
0 0 0 1131452 2076 171400 0 0 0 0 77 87 0 0 100 0 0
0 0 0 1131452 2076 171400 0 0 0 0 82 88 0 0 100 0 0
1 0 0 1131452 2076 171400 0 0 0 0 80 87 0 0 100 0 0
0 0 0 1131452 2076 171400 0 0 0 0 77 85 0 1 99 0 0
0 0 0 1131452 2076 171400 0 0 0 0 81 88 0 0 100 0 0
0 0 0 1131452 2076 171400 0 0 0 0 84 89 0 0 100 0 0
0 0 0 1131452 2076 171400 0 0 0 0 78 86 0 0 100 0 0
0 0 0 1131452 2076 171400 0 0 0 0 81 83 0 0 100 0 0
0 0 0 1131452 2076 171400 0 0 0 0 81 88 0 0 100 0 0
0 0 0 1131452 2076 171400 0 0 0 0 81 85 0 1 99 0 0
0 0 0 1131452 2076 171400 0 0 0 0 80 91 0 0 100 0 0
0 0 0 1131452 2076 171400 0 0 0 0 80 85 0 0 100 0 0
0 0 0 1131452 2076 171400 0 0 0 0 80 86 0 0 100 0 0
0 0 0 1131452 2076 171400 0 0 0 0 79 87 0 1 99 0 0
0 0 0 1131452 2076 171400 0 0 0 0 80 88 0 0 100 0 0
^C[root@zyshanlinux-001 ~]#
把本机器的文件同步到目标机器上去。
[root@zyshanlinux-001 ~]# vi 5.expect
#!/usr/bin/expect
set passwd "目标机器的登录密码"
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@zyshanlinux-001 ~]# chmod a+x 5.expect
[root@zyshanlinux-001 ~]# ./5.expect 192.168.106.130 "/tmp/12.txt"
spawn rsync -av /tmp/12.txt root@192.168.106.130:/tmp/12.txt
root@192.168.106.130's password:
sending incremental file list
sent 45 bytes received 12 bytes 38.00 bytes/sec
total size is 5 speedup is 0.09
[root@zyshanlinux-001 ~]#
构建文件分发系统
-
需求背景
对于大公司而言,肯定时不时会有网站或者配置文件更新,而且使用的机器肯定也是好多台,少则几台,多则几十甚至上百台。所以,自动同步文件是至关重要的。
-
实现思路
首先要有一台模板机器,把要分发的文件准备好,然后只要使用expect脚本批量把需要同步的文件分发到目标机器即可。
-
核心命令
rsync -av --files-from=list.txt / root@host:/
文件分发系统的实现:
1、rsync.expect 内容,同步时本地机与目标机必须有相同的路径,文件可以没有但目录必须要有;如果没有的话需要加上选项R,同步时级联创建目录路径spawn rsync -avR;所有目标的机器的密码必须一样或者用密钥认证登录。
vi rsync.expect
#!/usr/bin/expect
set passwd "目标机器的登录密码"
set host [lindex $argv 0]
set file [lindex $argv 1]
spawn rsync -av --files-from=$file / root@$host:/
expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
expect eof
2、ip.list内容,目标机器的IP
vi /tmp/ip.list
192.168.106.130
192.168.43.201
3、rsync.sh内容
[root@zyshanlinux-001 ~]# vi rsync.sh
#!/bin/bash
for ip in `cat /tmp/ip.list`
do
echo $ip
./rsync.expect $ip /tmp/file.list
done
4、file.list内容,发布的文件绝对路径
[root@zyshanlinux-001 ~]# vi /tmp/file.list
/tmp/12.txt
/root/13.txt
试验:
[root@zyshanlinux-001 ~]# chmod a+x rsync.expect
[root@zyshanlinux-001 ~]# sh -x rsync.sh
++ cat /tmp/ip.list
+ for ip in '`cat /tmp/ip.list`'
+ echo 192.168.106.130
192.168.106.130
+ ./rsync.expect 192.168.106.130 /tmp/file.list
spawn rsync -avR --files-from=/tmp/file.list / root@192.168.106.130:/
root@192.168.106.130's password:
building file list ... done
root/
sent 121 bytes received 19 bytes 280.00 bytes/sec
total size is 5 speedup is 0.04
+ for ip in '`cat /tmp/ip.list`'
+ echo 192.168.43.201
192.168.43.201
+ ./rsync.expect 192.168.43.201 /tmp/file.list
spawn rsync -avR --files-from=/tmp/file.list / root@192.168.43.201:/
root@192.168.43.201's password:
Permission denied, please try again.
root@192.168.43.201's password: [root@zyshanlinux-001 ~]#
批量远程执行命令
exe.expect 内容,该文件的后缀没有限定,但文件的内容的头必须是#!/usr/bin/expect,否则无法解析。
[root@zyshanlinux-001 ~]# vim exe.expect
#!/usr/bin/expect
set host [lindex $argv 0]
set passwd "目标机器的登录密码"
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@zyshanlinux-001 ~]# chmod a+x exe.expect
exe.sh 内容,文件路径要写绝对路径
[root@zyshanlinux-001 ~]# vi exe.sh
#!/bin/bash
for ip in `cat /tmp/ip.list`
do
echo $ip
./exe.expect $ip 'w;free -m;ls /tmp'
done
测试
[root@zyshanlinux-001 ~]# chmod a+x exe.expect
[root@zyshanlinux-001 ~]# sh -x exe.sh
++ cat /tmp/ip.list
+ for ip in '`cat /tmp/ip.list`'
+ echo 192.168.106.130
192.168.106.130
+ ./exe.expect 192.168.106.130 'w;free -m;ls /tmp'
spawn ssh root@192.168.106.130
root@192.168.106.130's password:
Last login: Thu Aug 2 22:28:08 2018 from 192.168.106.128
[root@zyshanlinux-02 ~]# w;free -m;ls /tmp
23:35:39 up 2:20, 1 user, load average: 0.00, 0.01, 0.05
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
root pts/0 192.168.106.128 23:35 0.00s 0.00s 0.00s w
total used free shared buff/cache available
Mem: 1831 557 1104 8 170 1111
Swap: 2047 0 2047
12.txt
mysql.sock
systemd-private-c8c8dddf3f4e4cfd87f2333294c9d88a-chronyd.service-Kng3xS
systemd-private-c8c8dddf3f4e4cfd87f2333294c9d88a-vgauthd.service-IVAlr8
systemd-private-c8c8dddf3f4e4cfd87f2333294c9d88a-vmtoolsd.service-PQVA7o
[root@zyshanlinux-02 ~]# + for ip in '`cat /tmp/ip.list`'
+ echo 192.168.43.201
192.168.43.201
+ ./exe.expect 192.168.43.201 'w;free -m;ls /tmp'
spawn ssh root@192.168.43.201
root@192.168.43.201's password:
Permission denied, please try again.
root@192.168.43.201's password:
Permission denied, please try again.
root@192.168.43.201's password: [root@zyshanlinux-001 ~]#
扩展:shell多线程 http://blog.lishiming.net/?p=448
给你提供一本电子书 链接:http://pan.baidu.com/s/1mg49Taw 密码:yk4b
shell习题做一下 http://www.apelearn.com/study_v2/chapter15.html#shll
linux shell命名管道FIFOhttp://blog.lishiming.net/?p=448