0620課的預習任務

20.27 分發系統介紹

由於業務迭代更新,需要更改代碼,如果機器很多,那麼久需要一個分發系統,可以把每段時間更新的代碼分別發佈到機器上去

分發系統就是上線的shell腳本,核心爲expect

expect是一種腳本語言,和shell很像,可以用它去實現傳輸文件和遠程執行命令,不需要去輸入密碼


20.28 expect腳本遠程登錄

安裝:

[root@arslinux-01 ~]# yum install -y expect

實例1:

自動遠程登錄

[root@arslinux-01 expect]# vim 1.expect
#! /usr/bin/expect
set host "192.168.194.132"
set passwd "12345678"
spawn ssh root@$host
expect {
"yes/no" { send "yes\r"; exp_continue}        //交互內容裏有 yes/no 需要怎麼辦
"assword:" { send "$passwd\r" }                //交互內容裏有 assword 怎麼辦
}
interact

expect 定義變量的方法:set 變量名

/root/.ssh/known_hosts 記錄歷史登錄服務器的文件,這樣再登錄不提示

interact 表示結束,停留在遠程的機器上(如果不加這一行,那麼登錄後馬上回退出)

(如果不用interact,而是expect eof ,那麼會停留在機器上幾秒,然後退出)

測試:

[root@arslinux-01 expect]# chmod a+x 1.expect
[root@arslinux-01 expect]# ll 1.expect
-rwxr-xr-x 1 root root 179 6月  20 06:44 1.expect
[root@arslinux-01 expect]# ./1.expect
spawn ssh [email protected]
[email protected]'s password:
Last login: Sun Jun 16 20:50:10 2019 from 192.168.194.1
[root@arslinux-02 ~]#

成功登錄2號機器


20.29 expect腳本遠程執行命令

實例2:

自動遠程登錄後,執行命令並退出

[root@arslinux-01 expect]# vim 2.expect
#!/usr/bin/expect
set user "root"
set passwd "123456"
spawn ssh [email protected]
expect {
"yes/no" { send "yes\r"; exp_continue }
"password:" { send "$passwd\r" }
}
expect "]*"
send "touch /tmp/12.txt\r"                //遇到 ]# 或 ]$ 執行什麼操作
expect "]*"
send "echo 1212 > /tmp/12.txt\r"
expect "]*"
send "exit\r"

測試:

[root@arslinux-01 expect]# chmod a+x 2.expect
[root@arslinux-01 expect]# ./2.expect
spawn ssh [email protected]
[email protected]'s password:
Last failed login: Thu Jun 20 07:15:12 CST 2019 from 192.168.194.130 on ssh:notty
There were 4 failed login attempts since the last successful login.
Last login: Thu Jun 20 07:13:41 2019 from 192.168.194.130
[root@arslinux-02 ~]# touch /tmp/12.txt
[root@arslinux-02 ~]# echo 1212 > /tmp/12.txt
[root@arslinux-02 ~]# [root@arslinux-01 expect]#

到2號機上查看

[root@arslinux-02 ~]# ll /tmp/12.txt
-rw-r--r-- 1 root root 5 6月  20 07:15 /tmp/12.txt
[root@arslinux-02 ~]# cat /tmp/12.txt
1212

成功


20.30 expect腳本傳遞參數

實例3:

傳遞參數

[root@arslinux-01 expect]# vim 3.expect
#!/usr/bin/expect
set user [lindex $argv 0]
set host [lindex $argv 1]
set passwd "123456"
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@arslinux-01 expect]# chmod a+x 3.expect

set user [lindex $argv 0],set host [lindex $argv 1],set cm [lindex $argv 2]分別表示第1,2,3個參數

設置用戶名,主機,命令(cm)

執行過程和之前腳本一致,只不過在執行命令時,需要向在命令行寫出3個參數傳遞到腳本中

如果想要傳遞多個命令,需要用雙引號括起來,並且命令之間用分號隔開

測試:

[root@arslinux-02 expect]# ./1.expect root 192.168.194.130 "ls;w;vmstat 1"
spawn ssh [email protected]
Last login: Thu Jun 20 22:18:29 2019 from 192.168.194.132
[root@arslinux-01 ~]# ls;w;vmstat 1
111         2222.txt.bak     bb.txt  f.txt          shell
11111.txt   222.txt          b.txt   F.txt          temp
123         234              B.txt   gakki.jpg.bz2  test
123.txt     234.tar          c.txt   grep           :WQ
1_hard.txt  2.txt            C.txt   log            zabbix.sql
1.sh        anaconda-ks.cfg  d.txt   logs           zrlog-1.7.1-baaecb9-release.war
1_soft.txt  arslinux         D.txt   newfile
1.txt       A.txt            e.txt   oot
1.txz~      awk              E.txt   sed
22:19:15 up  1:37,  3 users,  load average: 0.05, 0.06, 0.05
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
root     tty1                      22:09    8:35   0.13s  0.13s -bash
root     pts/0    192.168.194.1    21:00    3:39   0.12s  0.12s -bash
root     pts/1    192.168.194.132  22:19    3.00s  0.03s  0.01s w
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
3  0      0  60876   2200 279364    0    0    42    60  110  244  0  1 98  0  0
0  0      0  60892   2200 279396    0    0     0     0  118  216  0  0 100  0  0
0  0      0  60892   2200 279400    0    0     4    15  128  237  0  0 100  0  0
0  0      0  60892   2200 279400    0    0     0    10  128  240  0  1 99  0  0

因爲expect有默認超時時間,所有都會在10秒後會退出

如果想腳本執行不超時,可以設置 set timeout,指定一個數值,set timeout -1 永遠不超時,想要執行 5 秒就寫 5、執行某個命令就在命令 send "$cm\r" 下面 set time 指定秒數

出現問題:

[root@arslinux-01 expect]# ./3.expect root 192.168.194.132 "ls;w;vmstat 1"
spawn ssh [email protected]
[email protected]'s password: yum
Permission denied, please try again.

解決方法:

在 arslinux-01 上,編輯 /etc/ssh/sshd_config

找到 PermitRootLogin 取消#註釋,並改爲 yes

重啓 sshd ,再次嘗試 expect 應該沒有問題了


20.31 expect腳本同步文件

實例4:

自動同步文件

[root@arslinux-01 expect]# vim 4.expect
#!/usr/bin/expect
set passwd "123456"
spawn rsync -av [email protected]:/tmp/12121212.txt /tmp/
expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
expect eof
[root@arslinux-01 expect]# chmod a+x 4.expect

測試:

[root@arslinux-02 expect]# ./4.expect
spawn rsync -av [email protected]:/tmp/12121212.txt /tmp/
receiving incremental file list
12121212.txt
sent 43 bytes  received 93 bytes  12.95 bytes/sec
total size is 0  speedup is 0.00

expect eof  如果不加這條語句,那麼還沒有開始執行數據傳輸,就馬上結束了,甚至有可能還沒有遠程登錄成功,就已經退出來了,所以腳本里面必須要加這條語句。

不加 expect eof

[root@arslinux-01 expect]# ./4.expect
spawn rsync -av [email protected]:/tmp/1922168194132.txt /tmp/


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

實例5:

指定host和要同步的文件

[root@arslinux-01 expect]# vim 5.expect
#!/usr/bin/expect
set passwd "123456"
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@arslinux-01 expect]# chmod a+x 5.expect

測試:

[root@arslinux-01 expect]# ./5.expect 192.168.194.132 "/tmp/1234567.txt"
spawn rsync -av /tmp/7654321.txt [email protected]:/tmp/1234567.txt
sending incremental file list
1234567.txt
sent 93 bytes  received 35 bytes  12.19 bytes/sec
total size is 0  speedup is 0.00


20.33 構建文件分發系統

需求背景:

對於大公司而言,肯定時不時會有網站或者配置文件更新,而且使用的機器肯定也是好多臺,少則幾臺,多則幾十甚至上百臺。所以,自動同步文件是至關重要的。

實現思路:

首先要有一臺模板機器,把要分發的文件準備好,然後只要使用expect腳本批量把需要同步的文件分發到目標機器即可。

核心命令:

rsync -av --files-from=list.txt  /  root@host:/

實例6:

[root@arslinux-02 expect]# vim rsync.expect
#!/usr/bin/expect
set passwd "123456"
set host [lindex $argv 0]
set file [lindex $argv 1]
spawn rsync -avR --files-from=$file / root@$host:/
expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
expect eof
[root@arslinux-02 expect]# chmod a+x rsync.expect

file 內容:

[root@arslinux-02 expect]# vim /tmp/list.txt
/tmp/12123.txt
/root/shell/ceshi.sh
/root/linux2019/README.md

列表裏面文件的路徑,在另一臺機器上也要存在纔可以,如果沒有可以用 rsync -R 創建

iplist 內容:

[root@arslinux-02 expect]# vim /tmp/ip.txt
192.168.194.130
127.0.0.1

做密鑰認證可以省略密碼,防止密碼泄露

rsync.sh 內容:

[root@arslinux-02 expect]# vim rsync.sh
#!/bin/bash
for ip in `cat /tmp/ip.txt`
do
./rsync.expect $ip /tmp/list.txt
done

測試:

[root@arslinux-02 expect]# sh -x rsync.sh
++ cat /tmp/ip.txt
+ for ip in '`cat /tmp/ip.txt`'
+ ./rsync.expect 192.168.194.130 /tmp/list.txt
spawn rsync -avR --files-from=/tmp/list.txt / [email protected]:/
building file list ... done
root/
root/linux2019/
root/linux2019/README.md
root/shell/
root/shell/ceshi.sh
tmp/
tmp/12123.txt
sent 343 bytes  received 85 bytes  37.22 bytes/sec
total size is 12  speedup is 0.03
+ for ip in '`cat /tmp/ip.txt`'
+ ./rsync.expect 127.0.0.1 /tmp/list.txt
spawn rsync -avR --files-from=/tmp/list.txt / [email protected]:/
The authenticity of host '127.0.0.1 (127.0.0.1)' can't be established.
ECDSA key fingerprint is SHA256:56XmV3ETdeyOoI3O4uQmBzBston1io6oJGzG3tzxR3I.
ECDSA key fingerprint is MD5:70:fe:fe:67:05:ab:b9:25:88:67:98:5f:b5:c3:04:36.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '127.0.0.1' (ECDSA) to the list of known hosts.
[email protected]'s password: [root@arslinux-02 expect]#

在127.0.0.1傳遞時出錯,192.168.194.130可以,思路正確

思路:

執行 rsync.expect 腳本並且要傳遞兩個參數

而其中之一是多個ip中的一個,把 ip 寫到一個文本中,for 循環依次去讀一個ip,並傳遞到腳本中去

在 shell 腳本中寫此 for 循環,可以執行

把需要同步的文件絕對目錄寫入到 list.txt 中,這樣可以將需要同步的目錄依次同步到 ip.txt 中的機器


20.34 批量遠程執行命令

實例7:

定義 exe.expect

[root@arslinux-02 expect]# vim exe.expect
#!/usr/bin/expect
set host [lindex $argv 0]
set passwd "123456"
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@arslinux-02 expect]# chmod a+x exe.expect

定義exe.sh腳本

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

測試:

[root@arslinux-02 expect]# sh -x exe.sh
++ cat /tmp/ip.txt
+ for ip in '`cat /tmp/ip.txt`'
+ ./exe.expect 192.168.194.130 hostname
spawn ssh [email protected]
Last login: Fri Jun 21 06:50:46 2019 from 192.168.194.1
[root@arslinux-01 ~]# hostname
arslinux-01
[root@arslinux-01 ~]# + for ip in '`cat /tmp/ip.txt`'
+ ./exe.expect 127.0.0.1 hostname
spawn ssh [email protected]
[email protected]'s password:
Last failed login: Fri Jun 21 07:17:39 CST 2019 from localhost on ssh:notty
There were 2 failed login attempts since the last successful login.
Last login: Fri Jun 21 06:50:53 2019 from 192.168.194.1
[root@arslinux-02 ~]# hostname
arslinux-02

測試成功!

擴展:

shell多線程  http://blog.lishiming.net/?p=448

shell習題做一下  http://www.apelearn.com/study_v2/chapter15.html#shll


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