2018-08-01(expect分發系統)

20.27 分發系統介紹

公司業務逐漸擴大時,假如使用的網站或者APP的後端服務器所使用的語言是PHP,如果要想運行PHP代碼,需要配置一個lamp或lnmp的環境,最後還需要把代碼上傳到服務器上去,但是在平常工作中經常有一些新的業務改變,這個時候就需要去修改代碼,如果服務器不多還可以快速的在服務器上修改,但是如果有50臺或更多服務器,那麼就不可能直接在服務器進行修改了,這個時候就可以使用到分發系統這樣的上線工具進行上線,發佈上線代碼,所謂的分發系統也就是上線的shell腳本,最核心的東西就是expect,expect也可以說是一種腳本語言,和shell很像,可以用它去實現傳輸文件,還可以實現自動遠程登錄執行命令,不需要輸入密碼。

使用什麼工具上線代碼,所謂上線就是把開發人員寫的代碼發佈到線上環境去。

分發系統如何實現發佈上線代碼,首先要準備一臺模板的機器,這臺機器上的代碼是最新的代碼,是需要準備上線的代碼,另外要給這50臺電腦上線代碼,還需要知道50臺電腦的IP和對應的用戶密碼,然後使用expect腳本藉助於rsync把這些代碼推送到50臺機器上,假如說還需要執行一些命令,還可以使用expect遠程登錄後去執行命令,就是這樣的一個過程實現新代碼上線發佈。

20.28 expect腳本遠程登錄

1、yum安裝expect 軟件包

[root@localhost ~]# yum install -y expect

2、編寫expect腳本
示例1:通過expect腳本自動遠程登錄,並執行命令

[root@localhost ~]# cat ssh.expect 
#! /usr/bin/expect
#定義主機變量
set host "192.168.66.132" 
#定義密碼變量
set passwd "*****55"   
#遠程登陸機器的語句
spawn ssh root@$host  
#初次登陸會有yes和no的提示
expect {
"yes/no" { send "yes\r"; exp_continue}  
"password:" { send "$passwd\r" }
}
interact

•別忘記給腳本加上執行權限

[root@localhost ~]# chmod a+x ssh.expect

3、執行效果

[root@localhost ~]# ./ssh.expect 
spawn ssh [email protected]

Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.66.132' (ECDSA) to the list of known hosts.
[email protected]'s password: 
Last login: Fri Aug  3 15:30:28 2018 from 192.168.66.1
[root@lnmp-server ~]#    已經自動登錄到192.168.66.132 這臺機器

20.29 expect腳本遠程執行命令

示例2:通過expect腳本自動遠程登錄,並執行命令最後退出。

[root@localhost sbin]# vi touch.expect

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

expect {
"yes/no" { send "yes\r"; exp_continue}
"password:" { send "$passwd\r" }
}
expect "]*"
send "touch /tmp/test.txt\r"
expect "]*"
send "echo haha > /tmp/test.txt\r"
expect "]*"
send "exit\r"

•別忘記給腳本加上執行權限

[root@localhost sbin]# chmod a+x touch.expect

執行效果

[root@localhost sbin]# ./touch.expect       
spawn ssh [email protected]                #因爲不是第一次登陸了,所以沒有yes or no的提示
[email protected]'s password: 
Last login: Fri Aug  3 15:50:39 2018 from 192.168.66.131
[root@lnmp-server ~]# touch /tmp/test.txt
[root@lnmp-server ~]# echo haha > /tmp/test.txt
[root@lnmp-server ~]# [root@localhost sbin]#

查看192.168.66.132/tmp目錄是否自動創建了test.txt

[root@lnmp-server ~]# ll /tmp/test.txt 
-rw-r--r-- 1 root root 5 8月   3 15:50 /tmp/test.txt
[root@lnmp-server ~]# cat /tmp/test.txt 
haha

•比較ssh.expect和touch.expect腳本的區別,ssh.expect腳本僅僅是登錄進去,然後interact表示expect腳本結束了,但是會停留在機器上不會退出登錄的機器,touch.expect腳本登錄完之後,還需要執行幾條命令,最後纔是退出結束腳本

[root@localhost ~]# cat ssh.expect 
#! /usr/bin/expect
#定義主機變量
set host "192.168.66.132" 
#定義密碼變量
set passwd "*****55"   
#遠程登陸機器的語句
spawn ssh root@$host  
#初次登陸會有yes和no的提示
expect {
"yes/no" { send "yes\r"; exp_continue}  
"password:" { send "$passwd\r" }
}
interact

[root@localhost sbin]# cat touch.expect 
#!/usr/bin/expect
set user "root"
set passwd "*****55"
spawn ssh [email protected]
expect {
"yes/no" { send "yes\r"; exp_continue}
"password:" { send "$passwd\r" }
}
expect "]*"
send "touch /tmp/test.txt\r"
expect "]*"
send "echo haha > /tmp/test.txt\r"
expect "]*"
send "exit\r"

20.30 expect腳本傳遞參數

shell腳本可以傳遞參數,expect也是可以傳遞參數的,不同的是expect的參數是從0開始的
示例3:expect腳本傳遞參數

 [root@jimmylinux-001 sbin]# vi 3.expect 
 #!/usr/bin/expect
 set user [lindex $argv 0]
 set host [lindex $argv 1]
 set passwd "*****55"
 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@localhost sbin]# chmod +x 3.expect

執行腳本測試

###傳遞多條命令,需要使用雙引號引起來,中間用分號分隔。
[root@localhost sbin]# ./3.expect root 192.168.66.132 "ls;w;vmstat 1 3"
spawn ssh [email protected]
[email protected]'s password: 
Last login: Fri Aug  3 15:51:37 2018 from 192.168.66.131
[root@lnmp-server ~]# ls;w;vmstat 1 3
1.txt  2.sh  3.sh  anaconda-ks.cfg
 16:05:41 up 38 min,  2 users,  load average: 0.00, 0.01, 0.05
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
root     pts/0    192.168.66.1     15:30   14:37   0.00s  0.00s -bash
root     pts/1    192.168.66.131   16:05    0.00s  0.00s  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 272780   2076 155580    0    0    55     5   75   95  0  0 98  1  0
 0  0      0 272780   2076 155600    0    0     0     0   59   60  0  1 99  0  0
 0  0      0 272780   2076 155600    0    0     0     0   55   53  0  0 100  0  0

20.31 expect腳本同步文件

使用expect腳本實現在一臺機器上把文件同步到另外一臺機器上,這裏需要用到核心命令rsync,如果是手動方式進行同步,那麼還需要單獨輸入密碼,所以沒有腳本方式操作方便
•注意,因爲用到了rsync命令,所以兩邊機器都要安裝rsync

yum install -y rsync

示例4:自動同步文件

[root@localhost sbin]# vi 4.expect 
#!/usr/bin/expect
set passwd "*****55"
spawn rsync -av [email protected]:/tmp/test.txt /tmp/
expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
expect eof  #如果不加這條語句,那麼還沒有開始執行數據傳輸,就馬上結束了,甚至有可能還沒有遠程登錄成功,就已經退出來了,所以腳本里面必須要加這條語句。

給腳本加執行權限,並執行腳本測試

[root@localhost sbin]# chmod +x 4.expect
[root@localhost sbin]# ./4.expect 
spawn rsync -av [email protected]:/tmp/test.txt /tmp/
[email protected]'s password: 
receiving incremental file list
test.txt
sent 43 bytes  received 98 bytes  282.00 bytes/sec
total size is 5  speedup is 0.04
[root@localhost sbin]# ll /tmp/test.txt 
-rw-r--r-- 1 root root 5 8月   3 15:51 /tmp/test.txt

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

之前的3.expect文件默認是10秒鐘超時,當然也是可以增加超時時間甚至可以讓永久不超時。
只需要在腳本文件中添加設置timeout的變量即可

set timeout 3  設置超時秒數,如果是-1表示永久不會超時

示例5:指定host和要同步的文件,這種方式只適合同步一個文件。

[root@localhost sbin]# vi 5.expect
 #!/usr/bin/expect
  set passwd "*****55"
  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@localhost sbin]# chmod +x 5.expect 
[root@localhost sbin]# ./5.expect 192.168.66.132 ./5.expect 
spawn rsync -av ./5.expect [email protected]:./5.expect
[email protected]'s password: 
sending incremental file list
5.expect
sent 310 bytes  received 35 bytes  690.00 bytes/sec
total size is 217  speedup is 0.63
切換到加外一臺機查看
[root@lnmp-server ~]# ll
-rwxr-xr-x  1 root root   217 8月   3 16:27 5.expect

20.33 構建文件分發系統

需求背景:對於大公司而言,肯定時不時會有網站或者配置文件更新,而且使用的機器肯定也是好多臺,少則幾臺,多則幾十甚至上百臺。所以,自動同步文件是至關重要的。
實現思路:首先要有一臺模板機器,把要分發的文件準備好,然後只要使用expect腳本批量把需要同步的文件分發到目標機器即可。
•核心命令:rsync -av --files-from=list.txt / root@host:/
文件分發系統的實現
1、編寫 rsync.expect

[root@localhost sbin]# vi rsync.expect
#!/usr/bin/expect
set passwd "*****55"
set host [lindex $argv 0]
set file [lindex $argv 1]
spawn rsync -avR --files-from=$file / root@$host:/  
##如果不確定對方機器有相同的路徑,可以加-avR
expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
expect eof

•別忘記加上執行權限chmod +x rsync.expect

2、編寫文件列表 file.list

[root@localhost sbin]# vi /tmp/file.list
/tmp/test1.txt 
/tmp/test2.txt 
/tmp/test3.txt

3、編寫IP地址列表文件 ip.list

[root@localhost sbin]# vi /tmp/ip.list
192.168.66.129
192.168.66.132

4、創建 rsync.sh 循環調用rsync.expect去執行命令

[root@localhost sbin]# vi rsync.sh
#!/bin/bash
for ip in `cat /tmp/ip.list`
do
./rsync.expect $ip /tmp/file.list
done

5、測試效果

[root@localhost sbin]# sh rsync.sh
spawn rsync -avR --files-from=/tmp/file.list / [email protected]:/
[email protected]'s password: 
building file list ... done
tmp/
tmp/test1.txt
tmp/test2.txt
tmp/test3.txt
sent 168 bytes  received 56 bytes  89.60 bytes/sec
total size is 0  speedup is 0.00
spawn rsync -avR --files-from=/tmp/file.list / [email protected]:/
[email protected]'s password: 
building file list ... done
tmp/
tmp/test1.txt
tmp/test2.txt
tmp/test3.txt
sent 187 bytes  received 57 bytes  162.67 bytes/sec
total size is 0  speedup is 0.00
##切換到機器上查看
[root@lnmp-server ~]# ls /tmp/
test1.txt   test2.txt    test3.txt

20.34 批量遠程執行命令

想批量遠程執行命令,可以通過2個腳本來實現
1、創建 exe.expect 腳本

[root@localhost sbin]# vi exe.expect
#!/usr/bin/expect
set host [lindex $argv 0]
set passwd "*****55"
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"

2、添加執行權限

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

3、創建 exe.sh 腳本循環執行

[root@localhost sbin]# cat exe.sh 
#!/bin/bash
for ip in `cat /tmp/ip.list`
do 
./exe.expect $ip "hostname"
done

注意:/tmp/ip.list要自已創建
4、測試腳本

[root@lnmp-server ~]# [root@localhost sbin]# sh exe.sh 
spawn ssh [email protected]
[email protected]'s password: 
Last login: Wed Aug  1 20:16:03 2018 from 192.168.66.131
[root@localhost ~]# hostname
localhost.localdomain
[root@localhost ~]# spawn ssh [email protected]
[email protected]'s password: 
Last login: Fri Aug  3 16:57:29 2018 from 192.168.66.131
[root@lnmp-server ~]# hostname
lnmp-server

擴展:
shell多線程 http://blog.lishiming.net/?p=448
給你提供一本電子書 鏈接:http://pan.baidu.com/s/1mg49Taw 密碼:yk4b
shell習題做一下 http://www.apelearn.com/study_v2/chapter15.html#shll

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章