1. 程式人生 > >三十三節課筆記

三十三節課筆記

oot ellipsize 實例 jcp symbol 1.3 腳本 進行 腳本語言

20.27 分發系統介紹
20.28 expect腳本遠程登錄
20.29 expect腳本遠程執行命令
20.30 expect腳本傳遞參數
20.31 expect腳本同步文件
20.32 expect腳本指定host和要同步的文件
20.33 構建文件分發系統
20.34 批量遠程執行命令

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

20.27 分發系統介紹

由於業務叠代更新,經常需要更改代碼,如果機器很多,此時為了快速更新代碼就可以使用分發系統,把更新的代碼分別發布到機器上去。其中開源的上線代碼的軟件有很多,如git等等。這裏我們使用shell來編寫一個分發系統來上線代碼。核心使用expect腳本語言,它可以實現遠程執行命令,遠程傳輸數據等操作。

準備工作

1.準備1臺模版機器,裏面是包含有最新的代碼

2.每臺分發機器的IP地址和密碼

3.分發系統腳本

由於分發系統的核心是使用expect,因此先實踐幾個例子來熟悉expect的語法命令

20.28 expect腳本遠程登錄

實例1.自動遠程登錄

expect分發主機: expect-server 192.168.1.37
expect遠程主機: expect-client 192.168.1.38

1.在expect分發主機上安裝expect

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

2.編輯腳本

[root@expect-server ~]# vim /usr/local/sbin/expect1.exp
//添加如下內容
#!/usr/bin/expect
#定義變量
set host "192.168.1.38"
set passwd "Aa123456"
#執行命令
spawn ssh root@$host
#與遠程機器交互 截取特定信息 發送變量
expect {
"yes/no" { send "yes\r";exp_continue }
"password:" { send "$passwd\r" }
}
interact

// set 定義變量
// spawn 執行命令
// expect 使用expect語句進行交互
// \r表示回車
// exp_contunue表示繼續
// interact表示繼續交互
// expect eof表示停留遠程機器上一會兒再退出

//為了讓遠程登錄時候出現提示,可以清空/root/.ssh/known_hosts目錄
[root@expect-server ~]# > ~/.ssh/known_hosts

3.驗證

//添加執行權限
[root@expect-server ~]# chmod +x /usr/local/sbin/expect1.exp 
//執行腳本
[root@expect-server ~]# /usr/local/sbin/expect1.exp          
spawn ssh root@192.168.1.38
The authenticity of host ‘192.168.1.38 (192.168.1.38)‘ can‘t be established.
ECDSA key fingerprint is SHA256:dpBcqagKb3dleICUyCflHVb7zukCI3ViTczb9LroVU4.
ECDSA key fingerprint is MD5:7a:2c:c5:0a:02:fc:05:f1:8c:9a:26:f6:8b:7c:76:09.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added ‘192.168.1.38‘ (ECDSA) to the list of known hosts.
root@192.168.1.38‘s password: 
Last login: Fri Aug  3 00:43:44 2018 from 192.168.1.9
//成功實現遠程登錄

20.29 expect腳本遠程執行命令

實例2.自動遠程登錄,並執行命令並退出

1.編輯腳本

[root@expect-server ~]# vim /usr/local/sbin/expect2.exp
//添加如下內容
#!/usr/bin/expect
set user "root"
set host "192.168.1.38"
set passwd "Aa123456"
spawn ssh $user@$host
expect {
"yes/no" {send "yes\r";exp_continue}
"password:" {send "$passwd\r"}
}
expect "]*"
send "touch /tmp/test.aa\r"
expect "]*"
send "echo 111 >/tmp/test.aa\r"
expect "]*"
send "exit\r"

2.驗證

[root@expect-server ~]# chmod +x !$
chmod +x /usr/local/sbin/expect2.exp
[root@expect-server ~]# /usr/local/sbin/expect2.exp
spawn ssh root@192.168.1.38
root@192.168.1.38‘s password: 
Last login: Fri Aug  3 01:01:07 2018 from 192.168.1.37
[root@expect-client ~]# touch /tmp/test.aa
[root@expect-client ~]# echo 111 >/tmp/test.aa
[root@expect-client ~]# [root@expect-server ~]# 

[root@expect-server ~]# /usr/local/sbin/expect1.exp
spawn ssh root@192.168.1.38
root@192.168.1.38‘s password: 
Last login: Fri Aug  3 01:10:41 2018 from 192.168.1.37
[root@expect-client ~]# cat /tmp/test.aa 
111
[root@expect-client ~]# 

20.30 expect腳本傳遞參數

實例3.遠程傳遞參數

1.編輯腳本

[root@expect-server ~]# vim /usr/local/sbin/expect3.exp
//添加如下內容
#!/usr/bin/expect
set user [lindex $argv 0]
set host [lindex $argv 1]
set passwd "Aa123456"
set cmd [lindex $argv 2]
spawn ssh $user@$host
expect {
"yes/no" {send "yes\r"}
"password:" {send "$passwd\r"}
}
expect "]*"
send "$cmd\r"
expect "]*"
send "exit\r"

2.測試

[root@expect-server ~]# chmod +x !$
chmod +x /usr/local/sbin/expect3.exp
[root@expect-server ~]# /usr/local/sbin/expect3.exp root 192.168.1.38 "ls;w"
spawn ssh root@192.168.1.38
root@192.168.1.38‘s password: 
Last login: Fri Aug  3 01:11:41 2018 from 192.168.1.37
[root@expect-client ~]# ls;w
anaconda-ks.cfg  original-ks.cfg
 01:16:30 up 39 min,  3 users,  load average: 0.00, 0.01, 0.02
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
root     pts/0    192.168.1.9      00:43    9:34   0.12s  0.10s ssh 192.168.1.37
root     pts/1    192.168.1.37     01:01    9:34   0.06s  0.06s -bash
root     pts/2    192.168.1.37     01:16    0.00s  0.01s  0.00s w
[root@expect-client ~]# [root@expect-server ~]# 

//當要輸入參數裏面有多個命令是需要用""雙引號括起來並使用;分號分開


//可以在命令行的後面增加set timeout 來指定命令的超時時間 -1為永遠
#!/usr/bin/expect
set user [lindex $argv 0]
set host [lindex $argv 1]
set passwd "Aa123456"
set cmd [lindex $argv 2]
spawn ssh $user@$host
expect {
"yes/no" {send "yes\r"}
"password:" {send "$passwd\r"}
}
expect "]*"
send "$cmd\r"
set timeout -1
expect "]*"
send "exit\r"

[root@expect-client ~]# [root@expect-server ~]# /usr/local/sbin/expect3.exp root 192.168.1.38 "vmstat -1"^C
[root@expect-server ~]# /usr/local/sbin/expect3.exp root 192.168.1.38 "vmstat 1" 
spawn ssh root@192.168.1.38
root@192.168.1.38‘s password: 
Last login: Fri Aug  3 01:20:14 2018 from 192.168.1.37
[root@expect-client ~]# 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 780968   2076 120952    0    0    38     5   70   87  0  0 100  0  0
 0  0      0 780968   2076 120936    0    0     0     0   51   53  0  0 100  0  0
 0  0      0 780968   2076 120936    0    0     0     0   50   43  0  0 100  0  0
 0  0      0 780968   2076 120936    0    0     0    24   40   39  0  0 100  0  0
 0  0      0 780968   2076 120936    0    0     0     0   72   74  0  2 98  0  0
^C[root@expect-server ~]# 
//每隔1秒執行一次vmstat命令

20.31 expect腳本同步文件

實例4.自動同步文件

1.編輯腳本

[root@expect-server ~]# vim /usr/local/sbin/expect4.exp
//添加如下內容
#!/usr/bin/expect
set passwd "Aa123456"
spawn rsync -av root@192.168.1.38:/tmp/test.aa /tmp/
expect {
"yes/no" {send "yes\r"}
"password:" {send "$passwd\r"}
}
expect eof

//如果沒有安裝rsync,可以用yum -y install rsync安裝

2.測試

//設定執行權限
[root@expect-server ~]# chmod +x /usr/local/sbin/expect4.exp 
[root@expect-server ~]# /usr/local/sbin/expect4.exp 
spawn rsync -av root@192.168.1.38:/tmp/test.aa /tmp/
root@192.168.1.38‘s password: 
receiving incremental file list
test.aa

sent 30 bytes  received 84 bytes  228.00 bytes/sec
total size is 4  speedup is 0.04
//已經把192.168.1.38上的test.aa文件自動同步過來本機了

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

實例5.指定host和同步單個文件

1.編輯腳本

[root@expect-server ~]# vim /usr/local/sbin/expect5.exp
//添加如下內容
!/usr/bin/expect
set passwd "Aa123456"
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

2.驗證

[root@expect-server ~]# chmod +x !$
chmod +x /usr/local/sbin/expect5.exp
[root@expect-server ~]# /usr/local/sbin/expect5.exp 192.168.1.38 /tmp/test.aa 
spawn rsync -av /tmp/test.aa root@192.168.1.38:/tmp/test.aa
root@192.168.1.38‘s password: 
sending incremental file list
test.aa

sent 91 bytes  received 34 bytes  250.00 bytes/sec
total size is 4  speedup is 0.03

20.33 構建文件分發系統

分發系統中首先用expect編寫遠程同步腳本 並指定文件列表和目標IP列表 然後使用shell腳本調用expect來同步文件。
這裏每臺機器必須使用同樣的密碼才可以同步,也可以讓機器之前使用密鑰登錄。還有讓每臺機器都安裝上rsync
其核心命令為rsync -av --files-from=list.txt / root@host:/

1.編輯expect腳本

[root@expect-server ~]# vim /usr/local/sbin/sync.exp
//添加如下內容
#!/usr/bin/expect
set passwd "Aa123456"
set host [lindex $argv 0]
set file [lindex $argv 1]
#--file-from指定文件列表路徑 -R表示同步時目標會級聯創建目錄
spawn rsync -avR --files-from=$file / root@$host:/
expect {
"yes/no" {send "yes\r"}
"password:" {send $passwd\r}
}
expect eof

[root@expect-server ~]# chmod +x !$
chmod +x /usr/local/sbin/sync.exp

2.創建ip.list 同步機器的IP列表

[root@expect-server ~]# vim /tmp/ip.txt
//內容如下
192.168.1.38

3.創建file.list 需要同步文件的列表

[root@expect-server ~]# vim /tmp/file.list
//添加如下內容
/tmp/test
/tmp/test.aa

4.創建 rsync.sh 腳本

[root@expect-server ~]# vim /usr/local/sbin/rsync.sh
//添加如下內容
#!/bin/bash
for i in `cat /tmp/ip.list`
do
        ./rsync.exp $i /tmp/file.list
done

5.測試

[root@expect-server ~]# chmod +x /usr/local/sbin/rsync.sh 
[root@expect-server ~]# sh +x /usr/local/sbin/rsync.sh  
spawn rsync -avR --files-from=/tmp/file.list / root@192.168.1.38:/
root@192.168.1.38‘s password: 
building file list ... done
tmp/
tmp/test

sent 119 bytes  received 37 bytes  312.00 bytes/sec
total size is 8  speedup is 0.05

20.34 批量遠程執行命令

當同步完代碼後有可能需要批量地重啟服務,因此還需要批量遠程執行命令,類似於自動化。
這裏是用expect編寫執行命令的腳本並用shell腳本來批量調用它。

1.編輯expect腳本

[root@expect-server ~]# vim /usr/local/sbin/execute.exp
//內容如下
#!/usr/bin/expect
set passwd "Aa123456"
set host [lindex $argv 0]
set cmd [lindex $argv 1]
spawn ssh root@$host
expect {
"yes/no" {send "yes\r"}
"password:" {send "$passwd\r"}
}
expect "]*"
send "$cmd\r"
expect "]*"
send "exit\r"

2.編寫shell腳本

[root@expect-server ~]# vim /usr/local/sbin/execute.sh
#!/bin/bash
for i in $(cat /tmp/ip.list)
do
        echo $i
        /usr/local/sbin/execute.exp $i "systemctl status httpd.service "
done

3.測試

[root@expect-server sbin]# chmod +x /usr/local/sbin/execute.exp /usr/local/sbin/execute.sh
"execute.sh" 6L, 138C written                                                                                                                          
[root@expect-server sbin]# /usr/local/sbin/execute.sh                                     
192.168.1.38
spawn ssh [email protected]
[email protected]‘s password: 
Last login: Fri Aug  3 02:40:00 2018 from 192.168.1.37
[root@expect-client ~]# systemctl status httpd.service 
httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled; vendor preset: disabled)
   Active: active (running) since Fri 2018-08-03 02:40:07 CST; 2min 22s ago
     Docs: man:httpd(8)
           man:apachectl(8)
  Process: 16668 ExecStop=/bin/kill -WINCH ${MAINPID} (code=exited, status=0/SUCCESS)
 Main PID: 16678 (httpd)
   Status: "Total requests: 0; Current requests/sec: 0; Current traffic:   0 B/sec"
   CGroup: /system.slice/httpd.service
           ├─16678 /usr/sbin/httpd -DFOREGROUND
           ├─16679 /usr/sbin/httpd -DFOREGROUND
           ├─16680 /usr/sbin/httpd -DFOREGROUND
           ├─16681 /usr/sbin/httpd -DFOREGROUND
           ├─16682 /usr/sbin/httpd -DFOREGROUND
           └─16683 /usr/sbin/httpd -DFOREGROUND

Aug 03 02:40:01 expect-client systemd[1]: Starting The Apache HTTP Server...
Aug 03 02:40:07 expect-client httpd[16678]: AH00558: httpd: Could not reliably determine the server‘s fully qualified domain name, using fe80::20c:29ff:fea7...is message
Aug 03 02:40:07 expect-client systemd[1]: Started The Apache HTTP Server.
Hint: Some lines were ellipsized, use -l to show in full.

三十三節課筆記