公司業務逐漸擴大時,假如使用的網站或者APP的後端服務器所使用的語言是PHP,若是要想運行PHP代碼,須要配置一個lamp或lnmp的環境,最後還須要把代碼上傳到服務器上去,可是在日常工做中常常有一些新的業務改變,這個時候就須要去修改代碼,若是服務器很少還能夠快速的在服務器上修改,可是若是有50臺或更多服務器,那麼就不可能直接在服務器進行修改了,這個時候就可使用到分發系統這樣的上線工具進行上線,發佈上線代碼,所謂的分發系統也就是上線的shell腳本,最核心的東西就是expect,expect也能夠說是一種腳本語言,和shell很像,能夠用它去實現傳輸文件,還能夠實現自動遠程登陸執行命令,不須要輸入密碼。html
使用什麼工具上線代碼,所謂上線就是把開發人員寫的代碼發佈到線上環境去。linux
分發系統如何實現發佈上線代碼,首先要準備一臺模板的機器,這臺機器上的代碼是最新的代碼,是須要準備上線的代碼,另外要給這50臺電腦上線代碼,還須要知道50臺電腦的IP和對應的用戶密碼,而後使用expect腳本藉助於rsync把這些代碼推送到50臺機器上,假如說還須要執行一些命令,還可使用expect遠程登陸後去執行命令,就是這樣的一個過程實現新代碼上線發佈。shell
一、yum安裝expect 軟件包後端
[root@localhost ~]# yum install -y expect
二、編寫expect腳本
示例1:經過expect腳本自動遠程登陸,並執行命令bash
[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
三、執行效果多線程
[root@localhost ~]# ./ssh.expect spawn ssh root@192.168.66.132 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. root@192.168.66.132's password: Last login: Fri Aug 3 15:30:28 2018 from 192.168.66.1 [root@lnmp-server ~]# 已經自動登陸到192.168.66.132 這臺機器
示例2:經過expect腳本自動遠程登陸,並執行命令最後退出。dom
[root@localhost sbin]# vi touch.expect #!/usr/bin/expect set user "root" set passwd "*****55" spawn ssh $user@192.168.66.132 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"
•別忘記給腳本加上執行權限ssh
[root@localhost sbin]# chmod a+x touch.expect
執行效果ide
[root@localhost sbin]# ./touch.expect spawn ssh root@192.168.66.132 #由於不是第一次登錄了,因此沒有yes or no的提示 root@192.168.66.132'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 $user@192.168.66.132 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"
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 root@192.168.66.132 root@192.168.66.132'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
使用expect腳本實如今一臺機器上把文件同步到另一臺機器上,這裏須要用到核心命令rsync,若是是手動方式進行同步,那麼還須要單獨輸入密碼,因此沒有腳本方式操做方便
•注意,由於用到了rsync命令,因此兩邊機器都要安裝rsync
yum install -y rsync
示例4:自動同步文件
[root@localhost sbin]# vi 4.expect #!/usr/bin/expect set passwd "*****55" spawn rsync -av root@192.168.66.132:/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 root@192.168.66.132:/tmp/test.txt /tmp/ root@192.168.66.132'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
以前的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 root@192.168.66.132:./5.expect root@192.168.66.132'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
需求背景:對於大公司而言,確定時不時會有網站或者配置文件更新,並且使用的機器確定也是好多臺,少則幾臺,多則幾十甚至上百臺。因此,自動同步文件是相當重要的。
實現思路:首先要有一臺模板機器,把要分發的文件準備好,而後只要使用expect腳本批量把須要同步的文件分發到目標機器便可。
•核心命令:rsync -av --files-from=list.txt / root@host:/
文件分發系統的實現
一、編寫 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
二、編寫文件列表 file.list
[root@localhost sbin]# vi /tmp/file.list /tmp/test1.txt /tmp/test2.txt /tmp/test3.txt
三、編寫IP地址列表文件 ip.list
[root@localhost sbin]# vi /tmp/ip.list 192.168.66.129 192.168.66.132
四、建立 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
五、測試效果
[root@localhost sbin]# sh rsync.sh spawn rsync -avR --files-from=/tmp/file.list / root@192.168.66.129:/ root@192.168.66.129'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 / root@192.168.66.132:/ root@192.168.66.132'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
想批量遠程執行命令,能夠經過2個腳原本實現
一、建立 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"
二、添加執行權限
[root@localhost sbin]# chmod +x exe.expect
三、建立 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要自已建立
四、測試腳本
[root@lnmp-server ~]# [root@localhost sbin]# sh exe.sh spawn ssh root@192.168.66.129 root@192.168.66.129'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 root@192.168.66.132 root@192.168.66.132'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