現在一些比較大的企業,大都使用了負載均衡,而有時由於一些程序要更改,或者有些bug要修改,快速更新代碼等,若是僅是幾臺server的話,很簡單,把已經改好的程序拷過去,或者rsync遠程推送,再或者網上NFS共享一下就能夠了;但若是有幾十臺幾百臺,那樣的方法會太繁瑣,此時就能夠用expect來批量實現分發任務。shell
expect:一個實現自動交互功能的軟件套件,基於Tcl的一種腳本語言,具備簡單的語法;vim
功 能 :實現自動登陸遠程機器,並自動執行命令;和shell腳本結合,能夠實現徹底自動化;bash
注 意:如果使用不帶密碼的密鑰驗證一樣能夠實現自動登陸和自動遠程執行命令。但當不能使用密鑰驗證的時候,咱們就沒有辦法了。因此,這時只知道對方機器的帳號和密碼能夠經過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 ~]#
在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
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
在一臺機器上把文件同步到多臺機器上;核心命令,就是用的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
編輯指定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 爲永遠不超時。
需求背景:
對於大公司而言,確定時不時會有網站或者配置文件更新,並且使用的機器確定也是好多臺,少則幾臺,多則幾十甚至上百臺。因此,自動同步文件是相當重要的。
實現思路:
首先要有一臺模板機器,把要分發的文件準備好,而後只要使用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
分發系統還有一個重要的關鍵是,確保同步的機器的密碼一致,不然將不能實現同步;因此這就存在一個弊端,一旦腳本暴露,將會讓別人知道如何登錄你機器;固然也有對應的解決辦法,那就是使用密鑰認證。
當同步完代碼後有可能須要批量地重啓服務,所以還須要批量遠程執行命令,相似於自動化。 這裏是用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]#