第二十章、shell編程(下)

20.27 分發系統介紹
20.28 expect腳本遠程登陸
20.29 expect腳本遠程執行命令
20.30 expect腳本傳遞參數
20.31 expect腳本同步文件
20.32 expect腳本指定host和要同步的文件
20.33 構建文件分發系統
20.34 批量遠程執行命令
20.35 擴展
 
 
20.27 分發系統介紹
shell項目---分發系統
功能:
  • 能夠傳輸文件到大量機器;
  • 能夠遠程執行命令不須要輸入密碼;
 
 
20.28 expect腳本遠程登陸
 yum install -y expect      安裝expect包
 
•  自動遠程登陸
cd  /usr/local/sbin/
vi 1.expect
#! /usr/bin/expect
#定義變量,遠程登陸機器的ip和密碼
set host "192.168.233.129"
set passwd "1234"
#經過一種ssh方式登陸機器
spawn ssh root@$host
#第一次遠程ssh登陸時會問是否創建鏈接,當遇到yes或no時,發送yes;遇到password時,發送$passwd(定義密碼的變量值)
#\r表示回車
expect {
"yes/no" { send "yes\r"; exp_continue}
"password:" { send "$passwd\r" }
}
interact
#若沒加interact,登陸後會退出來,但expect命令還沒結束
 
執行expect文件
chmod a+x 1.expect; ./1.expect
[root@xinlinux-03 sbin]# ./1.expect
spawn ssh root@192.168.233.129
root@192.168.233.129's password:
Last login: Fri Oct 26 15:49:08 2018 from 192.168.233.150
[root@xinlinux-01 ~]#
 
 
退出遠程機器的三種方式:
  • interact 表示停留在遠程的機器上,不須要退出;
  • expect eof  表示暫停一段時間,再退出來
  • exit 表示直接退出
 
 
20.29 expect腳本遠程執行命令
•  自動遠程登陸後,執行命令並退出
vi 2.expect
#!/usr/bin/expect
#定義user和password的變量
set user "root"
set passwd "1234"
#經過另外一種ssh方式登陸機器
spawn ssh $user@192.168.233.129
expect {
"yes/no" { send "yes\r"; exp_continue}
"password:" { send "$passwd\r" }
}
#普通用戶登陸後是]$,root用戶登錄後是]#,"]*"通配,不論是普通用戶仍是root用戶,遇到"]*"就前後執行touch、echo、exit命令
expect "]*"
send "touch /tmp/12.txt\r"
expect "]*"
send "echo 1212 > /tmp/12.txt\r"
expect "]*"
send "exit\r"
 
執行expect文件
chmod a+x 2.expect; ./2.expect
[root@xinlinux-03 sbin]# ./2.expect
spawn ssh root@192.168.233.129
root@192.168.233.129's password:
Last login: Fri Oct 26 15:50:55 2018 from 192.168.233.150
[root@xinlinux-01 ~]# touch /tmp/12.txt
[root@xinlinux-01 ~]# echo 1212 > /tmp/12.txt
[root@xinlinux-01 ~]# [root@xinlinux-03 sbin]#
 
檢查是否實驗成功
./1.expect
ls -l /tmp/12.txt
cat /tmp/12.txt
[root@xinlinux-03 sbin]# ./1.expect
spawn ssh root@192.168.233.129
root@192.168.233.129's password:
Last login: Fri Oct 26 15:51:58 2018 from 192.168.233.150
[root@xinlinux-01 ~]# ls -l /tmp/12.txt
-rw-r--r-- 1 root root 5 10月 26 15:51 /tmp/12.txt
[root@xinlinux-01 ~]# cat /tmp/12.txt
1212
 
 
20.30 expect腳本傳遞參數
•  傳遞參數(就是設置內置變量)
vi 3.expect
#!/usr/bin/expect
#set定義內置變量和變量
#[lindex $argv 0]表示第一個參數,user是用戶
set user [lindex $argv 0]
#[lindex $argv 1]表示第二個參數,host是ip地址
set host [lindex $argv 1]
set passwd "1234"
#[lindex $argv 2]表示第三個參數,cm表示的是命令
set cm [lindex $argv 2]
spawn ssh $user@$host
expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
#$cm表示輸入命令
expect "]*"
send "$cm\r"
#expect有默認超時時間(是10秒),能夠設定超時時間,這裏timeout是10秒
set timeout 10
expect "]*"
send "exit\r"
 
 
執行expect文件
chmod a+x 3.expect
./3.expect  root 192.168.233.129 ls
#登陸機器執行ls命令(執行單條命令)
[root@xinlinux-03 sbin]# ./3.expect  root 192.168.233.129 ls
spawn ssh root@192.168.233.129
root@192.168.233.129's password:
Last login: Fri Oct 26 16:06:36 2018 from 192.168.233.150
[root@xinlinux-01 ~]# ls
1  1.txt  2_heard.txt  2.txt  anaconda-ks.cfg  test  yum.log
[root@xinlinux-01 ~]# [root@xinlinux-03 sbin]#
 
./3.expect  root 192.168.233.129  "ls;vmstat 1 1"
#登陸機器執行ls、vmstat命令(執行多條命令)
 
#若是expect的終端結束expect,那遠程登陸的expect命令也會結束
 
 
20.31 expect腳本同步文件
• 自動同步文件
vi 4.expect
#!/usr/bin/expect
set passwd "1234"
#經過rsync方式登陸同步文件
spawn rsync -av root@192.168.233.129:/tmp/12.txt /tmp/
expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
#同步文件時設置time out是行不通的
expect eof
 
執行expect文件
chmod a+x 4.expect; ./4.expect
[root@xinlinux-03 sbin]# chmod a+x 4.expect; ./4.expect
spawn rsync -av root@192.168.233.129:/tmp/12.txt /tmp/
root@192.168.233.129's password:
receiving incremental file list
12.txt
 
sent 43 bytes  received 97 bytes  280.00 bytes/sec
total size is 5  speedup is 0.04
 
 
20.32 expect腳本指定host和要同步的文件
• 指定host和要同步的文件(一次只能同步一個文件)
vi 5.expect
#!/usr/bin/expect
set passwd "1234"
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
##注意,file要寫絕對路徑
 
執行expect文件
chmod a+x 5.expect
./5.expect 192.168.233.129  "/tmp/12.txt"
[root@xinlinux-03 sbin]# ./5.expect 192.168.233.129  "/tmp/12.txt"
spawn rsync -av /tmp/12.txt root@192.168.233.129:/tmp/12.txt
root@192.168.233.129's password:
sending incremental file list
 
sent 45 bytes  received 12 bytes  38.00 bytes/sec
total size is 5  speedup is 0.09
 
 
20.33 構建文件分發系統
• 需求背景
對於大公司而言,確定時不時會有網站或者配置文件更新,並且使用的機器確定也是好多臺,少則幾臺,多則幾十甚至上百臺。因此,自動同步文件是相當重要的。
• 實現思路
首先要有一臺模板機器,把要分發的文件準備好,而後只要使用expect腳本批量把須要同步的文件分發到目標機器便可。
• 核心命令
rsync -av --files-from=list.txt  /  root@host:/
#list.txt文件列表,將要同步的大量文件寫入到這裏面;
#list.txt的路徑要用絕對路徑
 
• 文件分發系統的實現
• rsync.expect 內容
vi  rsync.expect
#!/usr/bin/expect
set passwd "1234"
set host [lindex $argv 0]
set file [lindex $argv 1]
#若是不能保證同步機器上有相對應文件的路徑,可在rsync處加上-R參數
spawn rsync -avR --files-from=$file / root@$host:/
expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
expect eof
 
•建立文件列表文件file.list
#同步時要保證傳輸文件的路徑在同步機器上有相同的路徑,例如同步/tmp/12.txt,那同步機器上要有/tmp/目錄
vi /tmp/file.list
例如:
/tmp/12.txt
/root/shell/1.sh
 
• ip.list內容(寫遠程同步機器ip)
vi /tmp/ip.list
192.168.233.129
192.168.233.132
......
#可用密鑰認證,這樣避免每臺機器都要輸入密碼
 
 
• rsync.sh 內容
#將須要同步機器的ip進行分發同步文件
vi rsync.sh
#!/bin/bash
for ip in `cat ip.list`
do
    echo $ip
    ./rsync.expect $ip /tmp/file.list
done
 
•開始執行分發文件
chmod a+x  rsync.expect
sh   rsync.sh
 
 
 
20.34 批量遠程執行命令
使用場景:同步完完文件後可能須要重啓一些服務
 
• exe.expect 內容
vi exe.expect
#!/usr/bin/expect
#host做爲第一個參數
set host [lindex $argv 0]
set passwd "1234"
#執行的命令做爲第二個參數
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 內容(執行同步機器的執行命令)
vi exe.sh
#!/bin/bash
for ip in `cat /tmp/ip.list`
do
    echo $ip
    ./exe.expect $ip "hostname"
done
 
•開始執行
chmod a+x exe.expect
sh exe.sh
 
 
20.35 擴展
 
給你提供一本電子書連接: http://pan.baidu.com/s/1mg49Taw  密碼:yk4b
 
 
20.35課堂筆記
1、shell中的變量
$#,表示參數個數
 
 
2、if判斷
判斷表達式格式:
一、比較字符時,只能用等於號,不能用-eq;例如: a='abc' ;  if [ $a == "abc" ];then echo ok;fi
 
二、比較數字時,要用-eq,若是用等號去比較,則會把數字當作字符串去比較;例如: a=10;if [ $a -eq 10 ];then echo ok;fi
 
三、寫多個條件時,條件之間要用-o隔開    [ $a -eq 10 -o $b -lt  10 ]
或者使用|| 或&&時,多個條件之間要用多箇中括號[ ]括起來      [ $a -eq 10 ] || [ $b -lt  10 ]
 
四、 if [ #a -gt 10 ]  能夠寫成  if((a>10))
 
 
3、select用法
#通常與case一塊兒用
select也是循環的一種,它比較適合 用在用戶選擇的狀況下
好比,咱們有一個這樣的需求,運行腳本後,讓用戶去選擇數字,選擇1,會運行w命令,選擇2運行top命令,選擇3運行free命令,選擇4退出。腳本這樣實現:
#!/bin/bash
echo "Please chose a number, 1: run w, 2: run top, 3: run free, 4: quit"
echo
select command in w top free quit
do
    case $command in
    w)
        w
       ;;
    top)
        top
        ;;
     free)
         free
         ;;
     quit)
        exit
         ;;
    *)
        echo "Please input a number:(1-4)."
         ;;
     esac
 done
執行結果以下:
sh select.sh
Please chose a number, 1: run w, 2: run top, 3: run free, 4: quit
 
1) w
2) top
3) free
4) quit
#? 1
16:03:40 up 32 days,  2:42,  1 user,  load average: 0.01, 0.08, 0.08
USER     TTY      FROM              LOGIN@   IDLE   JCPU   PCPU WHAT
root     pts/0    61.135.172.68    15:33    0.00s  0.02s  0.00s sh select.sh
 
#? 3
             total       used       free     shared    buffers     cached
Mem:       1020328     943736      76592          0      86840     263624
-/+ buffers/cache:     593272     427056
Swap:      2097144      44196    2052948
#?
 
咱們發現,select會默認把序號對應的命令列出來,每次輸入一個數字,則會執行相應的命令,命令執行完後並不會退出腳本。它還會繼續讓咱們再次輸如序號。序號前面的提示符,咱們也是能夠修改的,利用變量PS3便可,再次修改腳本以下:
 #!/bin/bash
 PS3="Please select a number: "
 echo "Please chose a number, 1: run w, 2: run top, 3: run free, 4: quit"
 echo
 select command in w top free quit
 do
     case $command in
     w)
         w
         ;;
     top)
        top
         ;;
     free)
         free
         ;;
     quit)
         exit
         ;;
     *)
         echo "Please input a number:(1-4)."
     esac
 done
若是想要腳本每次輸入一個序號後就自動退出,則須要再次更改腳本以下:
 #!/bin/bash
 PS3="Please select a number: "
 echo "Please chose a number, 1: run w, 2: run top, 3: run free, 4: quit"
 echo
 select command in w top free quit
 do
     case $command in
    w)
         w;exit
         ;;
     top)
         top;exit
         ;;
     free)
         free;exit
         ;;
     quit)
         exit
         ;;
    *)
         echo "Please input a number:(1-4).";exit
     esac
 done
 
 
4、for循環
#for循環是以空格做爲分隔符,所以文件名或內容中有空格的要注意,能夠改用while循環
 
#若是要for循環文件內容(內容含有空格),應該用 cat tmp.txt  |while read lne;do  echo  $line;done
 
 
5、while循環
#while ture 和while:都是表示死循環
相關文章
相關標籤/搜索