目錄html
二十3、 分發系統介紹
二十4、 expect腳本遠程登陸
二十5、 expect腳本遠程執行命令
二十6、 expect腳本傳遞參數
二十7、 expect腳本同步文件
二十8、 expect腳本指定host和要同步的文件
二十9、 構建文件分發系統
三10、 批量遠程執行命令
三11、 擴展git
因爲業務迭代更新,常常須要更改代碼,若是機器不少,此時爲了快速更新代碼就可使用分發系統,把更新的代碼分別發佈到機器上去。其中開源的上線代碼的軟件有不少,如git等等。這裏咱們使用shell來編寫一個分發系統來上線代碼。核心使用expect腳本語言,它能夠實現遠程執行命令,遠程傳輸數據等操做。shell
準備工做apache
1.準備1臺模版機器,裏面是包含有最新的代碼編程
2.每臺分發機器的IP地址和密碼vim
3.分發系統腳本bash
因爲分發系統的核心是使用expect,所以先實踐幾個例子來熟悉expect的語法命令多線程
實例1.自動遠程登陸dom
expect分發主機: expect-server 192.168.1.37
expect遠程主機: expect-client 192.168.1.38ssh
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 //成功實現遠程登陸
實例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 ~]#
實例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命令
實例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文件自動同步過來本機了
實例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
分發系統中首先用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
當同步完代碼後有可能須要批量地重啓服務,所以還須要批量遠程執行命令,相似於自動化。
這裏是用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 root@192.168.1.38 root@192.168.1.38'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.
shell多線程
http://blog.lishiming.net/?p=448
shell習題作一下
http://www.apelearn.com/study_v2/chapter15.html#shll