分發系統——expect

分發系統-expect

1、分發系統介紹

現在一些比較大的企業,大都使用了負載均衡,而有時由於一些程序要更改,或者有些bug要修改,快速更新代碼等,若是僅是幾臺server的話,很簡單,把已經改好的程序拷過去,或者rsync遠程推送,再或者網上NFS共享一下就能夠了;但若是有幾十臺幾百臺,那樣的方法會太繁瑣,此時就能夠用expect來批量實現分發任務。shell

  • expect:一個實現自動交互功能的軟件套件,基於Tcl的一種腳本語言,具備簡單的語法;vim

  • 功 能 :實現自動登陸遠程機器,並自動執行命令;和shell腳本結合,能夠實現徹底自動化;bash

  • 注 意:如果使用不帶密碼的密鑰驗證一樣能夠實現自動登陸和自動遠程執行命令。但當不能使用密鑰驗證的時候,咱們就沒有辦法了。因此,這時只知道對方機器的帳號和密碼能夠經過expect腳本實現登陸和遠程命令。服務器

2、expect腳本遠程登陸

本機試驗環境:負載均衡

  • 主機端 ying01 192.168.112.136
  • 遠程端1:ying02 192.168.112.138
  • 遠程端2:ying02 192.168.112.139

進入/usr/local/sbin/,建立一個expect腳本;ssh

[root@ying01 ~]# cd /usr/local/sbin/
[root@ying01 sbin]# vim 1.expect

#! /usr/bin/expect
set host "192.168.112.138"         //設置鏈接主機 
set passwd "ssss1234"              //設置密碼
spawn ssh root@$host               //執行命令
expect {                                   
"yes/no" { send "yes\r"; exp_continue}   //假如第一次登錄,須要yse,而後回車,繼續執行
"password:" { send "$passwd\r" }        //輸入密碼
}
interact                                //結束執行

代碼解釋: #! /usr/bin/expect 這一行告訴操做系統腳本里的代碼使用那一個shell來執行。測試

  • 在expect下 定義變量,用 set,好比 定義變量a爲1 :set a 1
  • expect 使用expect語句進行交互
  • \r表示回車
  • exp_continue 表示繼續 \r 表示換行 interact 繼續停留在這臺機器,不退出。
  • interact表示繼續交互

先用ssh 192.168.112.138 直接鏈接 ying02網站

[root@ying01 sbin]# ssh 192.168.112.138
root@192.168.112.138's password: 
Last login: Thu Aug  2 08:28:02 2018 from 192.168.112.1
[root@ying02 ~]# 登出
Connection to 192.168.112.138 closed.

授予1.expect 可執行權限,就能夠鏈接ying02機器ui

[root@ying01 sbin]# ./ 1.expect 
-bash: ./: 是一個目錄
[root@ying01 sbin]# ./1.expect 
-bash: ./1.expect: 權限不夠
[root@ying01 sbin]# chmod a+x 1.expect 
[root@ying01 sbin]# ./1.expect 
spawn ssh root@192.168.112.138
root@192.168.112.138's password: 
Last login: Thu Aug  2 15:22:34 2018 from 192.168.112.136
[root@ying02 ~]#

爲了讓遠程登陸時候出現提示,能夠清空/root/.ssh/known_hosts目錄;而後執行1.except,能夠看到腳本,自動執行spa

[root@ying01 sbin]# ls /root/.ssh/known_hosts
/root/.ssh/known_hosts
[root@ying01 sbin]# cat /root/.ssh/known_hosts     //有祕鑰
192.168.112.136 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBGrGzkv3dZLgXZVbExoHibbrjgfJ77FM/+pkylJJiPjNsuSPYpoPd3xJ6q7Uh8rKezv/1dAOI8Fh/Dnii9+GSH0=
192.168.112.138 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBGrGzkv3dZLgXZVbExoHibbrjgfJ77FM/+pkylJJiPjNsuSPYpoPd3xJ6q7Uh8rKezv/1dAOI8Fh/Dnii9+GSH0=
[root@ying01 sbin]# > /root/.ssh/known_hosts     //清空
[root@ying01 sbin]# cat /root/.ssh/known_hosts
[root@ying01 sbin]# ./1.expect                   //執行
spawn ssh root@192.168.112.138
The authenticity of host '192.168.112.138 (192.168.112.138)' can't be established.
ECDSA key fingerprint is SHA256:ZQlXi+kieRwi2t64Yc5vUhPPWkMub8f0CBjnYRlX2Iw.
ECDSA key fingerprint is MD5:ff:9f:37:87:81:89:fc:ed:af:c6:62:c6:32:53:7a:ad.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.112.138' (ECDSA) to the list of known hosts.
root@192.168.112.138's password: 
Last login: Thu Aug  2 16:06:27 2018 from 192.168.112.136
[root@ying02 ~]#

3、 expect腳本遠程執行命令

在ying01(192.168.112.136)上執行2.expect

[root@ying01 sbin]# vim 2.expect

#!/usr/bin/expect
set user "root"                        //設置用戶爲 root
set passwd "88888888"                  //設置密碼
spawn ssh $user@192.168.112.138        //鏈接遠程機器ying02

expect {                               //expect腳本內容
"yes/no" { send "yes\r"; exp_continue}
"password:" { send "$passwd\r" }
}
expect "]*"                            //遇到右側方括號執行下面命令
send "touch /tmp/12.txt\r"             //在/tmp下建立12.txt;回車
expect "]*"                            //上一語句執行完,遇到右側方括號,執行下面
send "echo 1212 > /tmp/12.txt\r"       //把1212寫入12.txt,回車
expect "]*"                            
send "exit\r"                          //輸入exit,退出,回到ying01機器

如今在ying02機器(192.168.112.138)上

[root@ying02 ~]# ls /tmp/12.txt              //12.txt存在
/tmp/12.txt
[root@ying02 ~]# ls -l /tmp/12.txt           //查看日期,證實是ying01遠程建立的
-rw-r--r-- 1 root root 5 8月   2 17:43 /tmp/12.txt
[root@ying02 ~]# cat /tmp/12.txt             //查看內容,只有1212,那麼證實試驗正確  
1212

4、expect腳本傳遞參數

expect腳本能夠接受從bash傳遞過來的參數.可使用[lindex $argv n]得到,n從0開始,分別表示第一個,第二個,第三個….參數

[root@ying01 sbin]# vim 3.expect

#!/usr/bin/expect
set user [lindex $argv 0]   //第一個參數
set host [lindex $argv 1]   //第二個參數
set passwd "88888888"
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@ying01 sbin]# chmod a+x 3.expect
[root@ying01 sbin]# ./3.expect root 192.168.112.138 "ls;pwd"    //帶參數執行;cm爲定義變量,能夠是任何命令,兩命令之間應分號隔開
spawn ssh root@192.168.112.138
root@192.168.112.138's password: 
Last login: Thu Aug  2 21:35:55 2018 from 192.168.112.136
[root@ying02 ~]# ls;pwd          //一、打開目錄  二、查看所在行 
123.txt  5555555.txt      NBA
520.txt  999.txt          zabbix-release-3.2-1.el7.noarch.rpm
555      anaconda-ks.cfg  [電影天堂-www.dy2018.net]深海之戰.720p.BD中文字幕.rmvb
/root
[root@ying02 ~]# [root@ying01 sbin]#

參數中能夠定義多個命令:如執行pwd、w、rm、ls -ld、vmstat 1等,命令之間用分號隔開

[root@ying01 sbin]# ./3.expect root 192.168.112.138 "pwd;w;rm -vf 2q.txt;ls -ld;vmstat 1"
spawn ssh root@192.168.112.138
root@192.168.112.138's password: 
Last login: Thu Aug  2 22:08:16 2018 from 192.168.112.136
[root@ying02 ~]# pwd;w;rm -vf 2q.txt;ls -ld;vmstat 1
/root                                                                //執行pwd
 22:09:08 up 13:42,  2 users,  load average: 0.00, 0.01, 0.05        //執行w
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
root     pts/0    192.168.112.1    08:28    2:12   0.04s  0.04s -bash
root     pts/1    192.168.112.136  22:09    0.00s  0.01s  0.00s w
已刪除"2q.txt"                                                       //執行rm
dr-xr-x---. 5 root root 4096 8月   2 22:09 .                         //執行ls
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----   //執行vmstat 1
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 1  0      0 1594252   2076 160452    0    0     1     1   51   46  0  0 100  0  0
 0  0      0 1594324   2076 160516    0    0     0     0   93   93  0  0 100  0  0
 0  0      0 1594324   2076 160516    0    0     0     0  101   92  0  0 100  0  0
 0  0      0 1594324   2076 160516    0    0     0     0   99   98  0  0 100  0  0
 0  0      0 1594324   2076 160516    0    0     0     0  115  103  0  0 100  0  0
 0  0      0 1594324   2076 160516    0    0     0     0  106  102  0  0 100  0  0
 0  0      0 1594324   2076 160516    0    0     0     0  105   95  0  0 100  0  0
 0  0      0 1594324   2076 160516    0    0     0    51  138  126  0  0 100  0  0
 0  0      0 1594324   2076 160516    0    0     0     0  107   94  0  0 100  0  0
 0  0      0 1594324   2076 160516    0    0     0     0  139  117  0  0 100  0  0

5、expect腳本同步文件

在一臺機器上把文件同步到多臺機器上;核心命令,就是用的rsync服務。

[root@ying01 sbin]# vim 4.expect

#!/usr/bin/expect
set passwd "88888888"
spawn rsync -av root@192.168.181.135:/tmp/12.txt /tmp/
expect {
"yes/no" { send "yes\r"}
"password:" { send $passwd\r}
}
expect eof  //結束expect匹配。

expect eof 語句解釋:

  • spawn執行的命令結果,會被expect捕捉到。由於spawn會啓動一個進程,只有這個進程的相關信息纔會被捕捉到,主要包括:標準輸入的提示信息,eof和timeout。
  • 在這裏eof是必須去匹配的,在spawn進程結束後會向expect發送eof,若是expect沒有匹配,那麼會當即退出遠程登陸,即操做失敗。

受權並測試

[root@ying01 sbin]# chmod a+x 4.expect
[root@ying01 sbin]# ./4.expect 
spawn rsync -av root@192.168.112.138:/tmp/12.txt /tmp/
root@192.168.112.138'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

6、expect腳本指定host和要同步的文件

編輯指定host要同步的文件的expect腳本

[root@ying01 sbin]# vim 5.expect

#!/usr/bin/expect
set passwd "88888888"
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@ying01 sbin]# chmod a+x 5.expect
[root@ying01 sbin]# ./5.expect 192.168.112.138 "/tmp/12.txt"
spawn rsync -av /tmp/12.txt root@192.168.112.138:/tmp/12.txt
root@192.168.112.138's password: 
sending incremental file list

sent 45 bytes  received 12 bytes  114.00 bytes/sec
total size is 5  speedup is 0.09

注意:

一、這裏要同步的文件,必要要寫絕對路徑;

二、備份的時候,注意時間限制;能夠設定 set timeout 定義超時時間(單位爲 秒) -1 爲永遠不超時。

7、構建文件分發系統

  • 需求背景

    對於大公司而言,確定時不時會有網站或者配置文件更新,並且使用的機器確定也是好多臺,少則幾臺,多則幾十甚至上百臺。因此,自動同步文件是相當重要的。

  • 實現思路

    首先要有一臺模板機器,把要分發的文件準備好,而後只要使用expect腳本批量把須要同步的文件分發到目標機器便可。

  • 核心命令

    rsync -av --files-from=list.txt / root@host:/ 注意:這裏的都是根目錄

    使用rsync 的 --files參數,能夠實現調用文件裏面的列表,進行多個文件遠程傳輸,進而實現文件分發文件分發系統的實現。

編寫rsync.expect 腳本

[root@ying01 sbin]# vim rsync.expect

#!/usr/bin/expect
set passwd "ssss1234"
set host [lindex $argv 0]
set file [lindex $argv 1]
spawn rsync -avR --files-from=$file / root@$host:/ 
# 上傳文件的列表是$file,咱們須要在list當中去定義; --file-from指定文件列表路徑 -R表示同步時目標會級聯建立目錄
expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
expect eof

由於實現分發系統,確定是由於須要分發的機器數量過大,因此,定義好了 文件 的 list 列表文件之後, 還須要配置 ip 的列表文件

[root@ying01 sbin]# vim /tmp/ip.list

192.168.112.138
192.168.112.139

建立file.list 須要同步文件的列表

[root@ying01 sbin]# vim /tmp/file.list

/tmp/12.txt
/root/NBA
/root/grep
/221.txt

建立一個rsync的shell腳本,腳本的目的:遍歷全部的server和list中的文件能夠同步到每臺服務器。

[root@ying01 sbin]# vim rsync.sh

#!/bin/bash

for ip in `cat /tmp/ip.list`
do
    echo $ip
    ./rsync.expect $i /tmp/file.list
done

受權rsync.expect腳本,並測試;

[root@ying01 sbin]# chmod a+x rsync.expect
[root@ying01 sbin]# sh -x rsync.sh       //執行rsync.sh腳本
++ cat /tmp/ip.list
+ for i in '`cat /tmp/ip.list`'
+ ./rsync.expect 192.168.112.138 /tmp/file.list   
spawn rsync -avR --files-from=/tmp/file.list / root@192.168.112.138:/
root@192.168.112.138's password: 
building file list ... done
root/
root/221.txt
root/NBA/
root/grep/

sent 6,860 bytes  received 44 bytes  13,808.00 bytes/sec
total size is 6,625  speedup is 0.96
+ for i in '`cat /tmp/ip.list`'
+ ./rsync.expect 192.168.112.139 /tmp/file.list
spawn rsync -avR --files-from=/tmp/file.list / root@192.168.112.139:/
root@192.168.112.139's password: 
building file list ... done
root/
root/221.txt
root/NBA/
root/grep/
tmp/

sent 6,863 bytes  received 47 bytes  13,820.00 bytes/sec
total size is 6,625  speedup is 0.96

此時查看ying02機器:192.168.112.138

[root@ying02 ~]# ls
123.txt  555          anaconda-ks.cfg  zabbix-release-3.2-1.el7.noarch.rpm
221.txt  5555555.txt  grep             [電影天堂-www.dy2018.net]深海之戰.720p.BD中文字幕.rmvb
520.txt  999.txt      NBA

ying03機器:192.168.112.139

[root@ying03 ~]# ls
123.txt  221.txt  520.txt  555  5555555.txt  999.txt  anaconda-ks.cfg  grep  NBA

分發系統還有一個重要的關鍵是,確保同步的機器的密碼一致,不然將不能實現同步;因此這就存在一個弊端,一旦腳本暴露,將會讓別人知道如何登錄你機器;固然也有對應的解決辦法,那就是使用密鑰認證。

8、批量遠程執行命令

當同步完代碼後有可能須要批量地重啓服務,所以還須要批量遠程執行命令,相似於自動化。 這裏是用expect編寫執行命令的腳本並用shell腳原本批量調用它。

[root@ying01 sbin]# vim exe.expect

#!/usr/bin/expect
set host [lindex $argv 0]
set passwd "ssss1234"
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"

再新建exe.sh的shell腳本,用來調用exe.expect腳本

[root@ying01 sbin]# vim exe.sh

#!/bin/bash
for ip in `cat /tmp/ip.list`                    //循環執行ip.list,注意ip清單是上個試驗的;
do
    echo $ip                       
    ./exe.expect $ip "w;free -m;ls /tmp"       //調用exe的expect腳本,並傳遞參數;
done

給exe.expect可執行權,並進行測試

[root@ying01 sbin]# chmod a+x exe.expect 

[root@ying01 sbin]# sh -x exe.sh 
++ cat /tmp/ip.list
+ for ip in '`cat /tmp/ip.list`'
+ echo 192.168.112.138
192.168.112.138
+ ./exe.expect 192.168.112.138 'w;free -m;ls /tmp'
spawn ssh root@192.168.112.138
root@192.168.112.138's password: 
Last login: Fri Aug  3 01:05:47 2018 from 192.168.112.136
[root@ying02 ~]# w;free -m;ls /tmp                                        //ying02下
 01:09:25 up 16:42,  2 users,  load average: 0.00, 0.01, 0.05
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
root     pts/0    192.168.112.1    四08   38:45   0.04s  0.04s -bash
root     pts/1    192.168.112.136  01:09    0.00s  0.00s  0.00s w
              total        used        free      shared  buff/cache   available
Mem:           1831         129        1542          16         159        1530
Swap:          3813           0        3813
12.txt
systemd-private-1516b7edb3f14f5e82677137397bcc40-chronyd.service-ozGmlD
systemd-private-1516b7edb3f14f5e82677137397bcc40-vgauthd.service-jhUiJk
systemd-private-1516b7edb3f14f5e82677137397bcc40-vmtoolsd.service-3Rpp62
[root@ying02 ~]# + for ip in '`cat /tmp/ip.list`'
+ echo 192.168.112.139
192.168.112.139
+ ./exe.expect 192.168.112.139 'w;free -m;ls /tmp'
spawn ssh root@192.168.112.139
root@192.168.112.139's password: 
Last login: Fri Aug  3 01:05:47 2018 from 192.168.112.136
[root@ying03 ~]# w;free -m;ls /tmp                                             //ying03下 
 01:09:25 up  1:21,  2 users,  load average: 0.00, 0.01, 0.05
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
root     pts/0    192.168.112.1    23:52   38:05   0.03s  0.03s -bash
root     pts/1    192.168.112.136  01:09    0.00s  0.02s  0.00s w
              total        used        free      shared  buff/cache   available
Mem:           1831         121        1571           8         138        1553
Swap:          3813           0        3813
12.txt
systemd-private-e8444e9da4d04018af38aa77476a1a09-chronyd.service-ZpE1xv
systemd-private-e8444e9da4d04018af38aa77476a1a09-vgauthd.service-fniGRJ
systemd-private-e8444e9da4d04018af38aa77476a1a09-vmtoolsd.service-r6srcB
[root@ying03 ~]# [root@ying01 sbin]#
相關文章
相關標籤/搜索