20.27 分发系统介绍
由于业务迭代更新,需要更改代码,如果机器很多,那么久需要一个分发系统,可以把每段时间更新的代码分别发布到机器上去
分发系统就是上线的shell脚本,核心为expect
expect是一种脚本语言,和shell很像,可以用它去实现传输文件和远程执行命令,不需要去输入密码
20.28 expect脚本远程登录
安装:
[root@arslinux-01 ~]# yum install -y expect
实例1:
自动远程登录
[root@arslinux-01 expect]# vim 1.expect #! /usr/bin/expect set host "192.168.194.132" set passwd "12345678" spawn ssh root@$host expect { "yes/no" { send "yes\r"; exp_continue} //交互内容里有 yes/no 需要怎么办 "assword:" { send "$passwd\r" } //交互内容里有 assword 怎么办 } interact
expect 定义变量的方法:set 变量名
/root/.ssh/known_hosts 记录历史登录服务器的文件,这样再登录不提示
interact 表示结束,停留在远程的机器上(如果不加这一行,那么登录后马上回退出)
(如果不用interact,而是expect eof ,那么会停留在机器上几秒,然后退出)
测试:
[root@arslinux-01 expect]# chmod a+x 1.expect [root@arslinux-01 expect]# ll 1.expect -rwxr-xr-x 1 root root 179 6月 20 06:44 1.expect
[root@arslinux-01 expect]# ./1.expect spawn ssh [email protected] [email protected]'s password: Last login: Sun Jun 16 20:50:10 2019 from 192.168.194.1 [root@arslinux-02 ~]#
成功登录2号机器
20.29 expect脚本远程执行命令
实例2:
自动远程登录后,执行命令并退出
[root@arslinux-01 expect]# vim 2.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"
测试:
[root@arslinux-01 expect]# chmod a+x 2.expect
[root@arslinux-01 expect]# ./2.expect spawn ssh [email protected] [email protected]'s password: Last failed login: Thu Jun 20 07:15:12 CST 2019 from 192.168.194.130 on ssh:notty There were 4 failed login attempts since the last successful login. Last login: Thu Jun 20 07:13:41 2019 from 192.168.194.130 [root@arslinux-02 ~]# touch /tmp/12.txt [root@arslinux-02 ~]# echo 1212 > /tmp/12.txt [root@arslinux-02 ~]# [root@arslinux-01 expect]#
到2号机上查看
[root@arslinux-02 ~]# ll /tmp/12.txt -rw-r--r-- 1 root root 5 6月 20 07:15 /tmp/12.txt [root@arslinux-02 ~]# cat /tmp/12.txt 1212
成功
20.30 expect脚本传递参数
实例3:
传递参数
[root@arslinux-01 expect]# vim 3.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"
[root@arslinux-01 expect]# chmod a+x 3.expect
set user [lindex $argv 0],set host [lindex $argv 1],set cm [lindex $argv 2]分别表示第1,2,3个参数
设置用户名,主机,命令(cm)
执行过程和之前脚本一致,只不过在执行命令时,需要向在命令行写出3个参数传递到脚本中
如果想要传递多个命令,需要用双引号括起来,并且命令之间用分号隔开
测试:
[root@arslinux-02 expect]# ./1.expect root 192.168.194.130 "ls;w;vmstat 1" spawn ssh [email protected] Last login: Thu Jun 20 22:18:29 2019 from 192.168.194.132 [root@arslinux-01 ~]# ls;w;vmstat 1 111 2222.txt.bak bb.txt f.txt shell 11111.txt 222.txt b.txt F.txt temp 123 234 B.txt gakki.jpg.bz2 test 123.txt 234.tar c.txt grep :WQ 1_hard.txt 2.txt C.txt log zabbix.sql 1.sh anaconda-ks.cfg d.txt logs zrlog-1.7.1-baaecb9-release.war 1_soft.txt arslinux D.txt newfile 1.txt A.txt e.txt oot 1.txz~ awk E.txt sed 22:19:15 up 1:37, 3 users, load average: 0.05, 0.06, 0.05 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT root tty1 22:09 8:35 0.13s 0.13s -bash root pts/0 192.168.194.1 21:00 3:39 0.12s 0.12s -bash root pts/1 192.168.194.132 22:19 3.00s 0.03s 0.01s w procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 3 0 0 60876 2200 279364 0 0 42 60 110 244 0 1 98 0 0 0 0 0 60892 2200 279396 0 0 0 0 118 216 0 0 100 0 0 0 0 0 60892 2200 279400 0 0 4 15 128 237 0 0 100 0 0 0 0 0 60892 2200 279400 0 0 0 10 128 240 0 1 99 0 0
因为expect有默认超时时间,所有都会在10秒后会退出
如果想脚本执行不超时,可以设置 set timeout,指定一个数值,set timeout -1 永远不超时,想要执行 5 秒就写 5、执行某个命令就在命令 send "$cm\r" 下面 set time 指定秒数
出现问题:
[root@arslinux-01 expect]# ./3.expect root 192.168.194.132 "ls;w;vmstat 1" spawn ssh [email protected] [email protected]'s password: yum Permission denied, please try again.
解决方法:
在 arslinux-01 上,编辑 /etc/ssh/sshd_config
找到 PermitRootLogin 取消#注释,并改为 yes
重启 sshd ,再次尝试 expect 应该没有问题了
20.31 expect脚本同步文件
实例4:
自动同步文件
[root@arslinux-01 expect]# vim 4.expect #!/usr/bin/expect set passwd "123456" spawn rsync -av [email protected]:/tmp/12121212.txt /tmp/ expect { "yes/no" { send "yes\r"} "password:" { send "$passwd\r" } } expect eof
[root@arslinux-01 expect]# chmod a+x 4.expect
测试:
[root@arslinux-02 expect]# ./4.expect spawn rsync -av [email protected]:/tmp/12121212.txt /tmp/ receiving incremental file list 12121212.txt sent 43 bytes received 93 bytes 12.95 bytes/sec total size is 0 speedup is 0.00
expect eof 如果不加这条语句,那么还没有开始执行数据传输,就马上结束了,甚至有可能还没有远程登录成功,就已经退出来了,所以脚本里面必须要加这条语句。
不加 expect eof
[root@arslinux-01 expect]# ./4.expect spawn rsync -av [email protected]:/tmp/1922168194132.txt /tmp/
20.32 expect脚本指定host和要同步的文件
实例5:
指定host和要同步的文件
[root@arslinux-01 expect]# vim 5.expect #!/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@arslinux-01 expect]# chmod a+x 5.expect
测试:
[root@arslinux-01 expect]# ./5.expect 192.168.194.132 "/tmp/1234567.txt" spawn rsync -av /tmp/7654321.txt [email protected]:/tmp/1234567.txt sending incremental file list 1234567.txt sent 93 bytes received 35 bytes 12.19 bytes/sec total size is 0 speedup is 0.00
20.33 构建文件分发系统
需求背景:
对于大公司而言,肯定时不时会有网站或者配置文件更新,而且使用的机器肯定也是好多台,少则几台,多则几十甚至上百台。所以,自动同步文件是至关重要的。
实现思路:
首先要有一台模板机器,把要分发的文件准备好,然后只要使用expect脚本批量把需要同步的文件分发到目标机器即可。
核心命令:
rsync -av --files-from=list.txt / root@host:/
实例6:
[root@arslinux-02 expect]# vim 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@arslinux-02 expect]# chmod a+x rsync.expect
file 内容:
[root@arslinux-02 expect]# vim /tmp/list.txt /tmp/12123.txt /root/shell/ceshi.sh /root/linux2019/README.md
列表里面文件的路径,在另一台机器上也要存在才可以,如果没有可以用 rsync -R 创建
iplist 内容:
[root@arslinux-02 expect]# vim /tmp/ip.txt 192.168.194.130 127.0.0.1
做密钥认证可以省略密码,防止密码泄露
rsync.sh 内容:
[root@arslinux-02 expect]# vim rsync.sh #!/bin/bash for ip in `cat /tmp/ip.txt` do ./rsync.expect $ip /tmp/list.txt done
测试:
[root@arslinux-02 expect]# sh -x rsync.sh ++ cat /tmp/ip.txt + for ip in '`cat /tmp/ip.txt`' + ./rsync.expect 192.168.194.130 /tmp/list.txt spawn rsync -avR --files-from=/tmp/list.txt / [email protected]:/ building file list ... done root/ root/linux2019/ root/linux2019/README.md root/shell/ root/shell/ceshi.sh tmp/ tmp/12123.txt sent 343 bytes received 85 bytes 37.22 bytes/sec total size is 12 speedup is 0.03 + for ip in '`cat /tmp/ip.txt`' + ./rsync.expect 127.0.0.1 /tmp/list.txt spawn rsync -avR --files-from=/tmp/list.txt / [email protected]:/ The authenticity of host '127.0.0.1 (127.0.0.1)' can't be established. ECDSA key fingerprint is SHA256:56XmV3ETdeyOoI3O4uQmBzBston1io6oJGzG3tzxR3I. ECDSA key fingerprint is MD5:70:fe:fe:67:05:ab:b9:25:88:67:98:5f:b5:c3:04:36. 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. [email protected]'s password: [root@arslinux-02 expect]#
在127.0.0.1传递时出错,192.168.194.130可以,思路正确
思路:
执行 rsync.expect 脚本并且要传递两个参数
而其中之一是多个ip中的一个,把 ip 写到一个文本中,for 循环依次去读一个ip,并传递到脚本中去
在 shell 脚本中写此 for 循环,可以执行
把需要同步的文件绝对目录写入到 list.txt 中,这样可以将需要同步的目录依次同步到 ip.txt 中的机器
20.34 批量远程执行命令
实例7:
定义 exe.expect
[root@arslinux-02 expect]# vim 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@arslinux-02 expect]# chmod a+x exe.expect
定义exe.sh脚本
[root@arslinux-02 expect]# cd ..
[root@arslinux-02 sbin]# vim exe.sh #!/bin/bash for ip in `cat /tmp/ip.list` do ./exe.expect $ip "hostname" done
测试:
[root@arslinux-02 expect]# sh -x exe.sh ++ cat /tmp/ip.txt + for ip in '`cat /tmp/ip.txt`' + ./exe.expect 192.168.194.130 hostname spawn ssh [email protected] Last login: Fri Jun 21 06:50:46 2019 from 192.168.194.1 [root@arslinux-01 ~]# hostname arslinux-01 [root@arslinux-01 ~]# + for ip in '`cat /tmp/ip.txt`' + ./exe.expect 127.0.0.1 hostname spawn ssh [email protected] [email protected]'s password: Last failed login: Fri Jun 21 07:17:39 CST 2019 from localhost on ssh:notty There were 2 failed login attempts since the last successful login. Last login: Fri Jun 21 06:50:53 2019 from 192.168.194.1 [root@arslinux-02 ~]# hostname arslinux-02
测试成功!
扩展:
shell多线程 http://blog.lishiming.net/?p=448
shell习题做一下 http://www.apelearn.com/study_v2/chapter15.html#shll