shell-6 expect

chunyang315發表於2018-04-26

expect指令碼同步檔案

  • 使用expect可以將一臺機器的檔案同步到另一臺機器中,指令碼4.expect如下
#!/usr/bin/expect
set passwd "xxxxxxx"
spawn rsync -av root@192.168.xxx.xxx:/tmp/1.txt /tmp/

expect {
"yes/on"  {send "yes\r"}
"passwoed:" {send "$passwd\r"}

 expect eof 

如果手動執行rsync,是需要手動輸入密碼的,那麼使用指令碼就很方便了。

:如果不加expect eof或是interact ,還沒開始傳輸就已經退出了遠端登入。它們的作用是給你一些時間讓你進行一些操作。


expect指令碼指定host和要同步的檔案

  • expect設定超時時間
#!/usr/bin/expect
set user [lindex $sargv 0] 
set host [lindex $sargv 1]
set paswwd "xxxxxx"
set cm [lindex $sargv 2]
spawn ssh  $user@$host
expect {
"yes/no" {send "yes\r" }
"password:" {send "$passwd\r"}
}
expect "]*"
send  "$cm\r"   
set timeout -1  //永久不超時
expect "]*"
send "exit\r"
  • 在指令碼中即使設定了set timeout -1 ,但是並沒有expect eof也是會馬上退出。
  • expect eof是expec的結尾。

    exit是一條命令,退出對方的終端。

  • 指定host和要同步的檔案 5.expect

#!/usr/bin/expect
set passwd "xxxxxxx"
set host [lindex $argv 0]  /引數1
set file [lindex $argv 1]  /引數2 ,需要同步的檔案,需要寫絕對路徑 
spawn rsync -av $file root@$host:$file 
expect {
"yes/no" { send "yes\r}"
"password:" { send "$passwd\r" }
}
expect eof
  • 加上執行許可權後,執行該命令
./4.expect 192.168.244.xxx  "/tmp/1.txt"

適合本地同步到遠端,單個檔案。


構建檔案分發系統

  • 需求背景
    對於大公司而言,肯定時不時會有網站或者配置檔案更新,而且使用的機器肯定也是很多臺,少則幾臺,多則幾十上百臺。所以,自動同步檔案是很重要的

  • 實現思路
    首先要有一臺模板機器,把要分發的檔案寫入到一個檔案列表中去,使用rsync –files-from=檔案列表,就能實現將檔案列表中的檔案同步到遠端中去。檔案列表需要使用絕對路徑。

  • 示例指令碼rsync.expect

#!/usr/bin/expect
set passwd "xxxxx"
set host [lindex $argv 0]
set file [lindex $argv 1]  //這裡file就是指檔案列表
spawn rsync -av --files-from=$file / root@$host:/
expect {
"yes/no" { send "yes\r" }
"password:" { send "$passwd\r" }
}
expect eof
  • 編寫file檔案列表 vi /tmp/file.list
/root/123/111/12.txt
/root/shell/1.sh
/tmp/1.txt

·這裡的路徑需要保證對方機器上也要有,裡面的檔案是我們才需要同步的,比如/root/shell目錄,對方機器上也存在才能同步,或者加-R選項,它會自動建立。

spawn rsync -avR --files-from=$file / root@$host:/

· 需要遠端同步的機器不止一臺,那麼需要ip列表
vi /tmp/ip.txt

192.168.244.xxx
192.168.244.xxx

做expect指令碼的前提是機器密碼需要是一樣的。如果不一樣,就只能每臺機器定義密碼,不足是expect指令碼一旦洩露,那裡面儲存的密碼就有可能被人猜到。另一種思路就是做祕鑰認證。就不要輸入密碼,那麼”password:” { send “$passwd\r” }可以不要。

  • 前面2個都有了,還需要建立rsync.sh
#!/bin/bash
for ip in `cat /tmp/ip.txt`
do 
  echo $ip
  ./rsync.expect  $ip  list.txt  //引數1 IP地址 引數2 檔案列表
  done 

目的是遍歷這些Ip地址

  • 執行前需要個rsync.expect執行許可權,才能正常的去執行它
    如果需要同步的檔案不存在會報錯。執行過後就可以在另一臺機器上檢視到被同步的檔案

批量遠端執行命令

  • 有了分發系統後,可以傳檔案了還不夠,比如傳輸檔案後需要執行一些命令

  • 批量執行命令指令碼exe.expect

#!/usr/bin/expect
set host [lindex $argv 0]
set passwd "xxxxxx"
set cm [lindex $argv 1]
spawn ssh root@$host
expexct {
"yes/no" { send "yes\r" }
"password:" { send "$passwd\r" }
}
expect "]*"
send "$cm\r"
expect "]*"
send "exit\r"
  • 需要定義exe.sh指令碼
#!/bin/bash
for ip in `cat /tmp/ip.txt`
do 
  ./exe.expect  $ip  "ip addr"  //後面用來指定需要執行的命令
  • Expect中最關鍵的四個命令是send,expect,spawn,interact。

send:用於向程式傳送字串
接收一個字串引數,並將該引數傳送到程式

expect:從程式接收字串
通常是用來等待一個程式的反饋

單一分支模式語法:

expect "hi" {send "You said hi"}
匹配到hi後,會輸出"you said hi"

多分支模式語法:

expect "hi" { send "You said hi\n" } \
"hello" { send "Hello yourself\n" } \
"bye" { send "That was unexpected\n" }
匹配到hi,hello,bye任意一個字串時,執行相應的輸出。等同於如下寫法:

expect {
"hi" { send "You said hi\n"}
"hello" { send "Hello yourself\n"}
"bye" { send "That was unexpected\n"}
}

spawn:啟動新的程式
spawn後的send和expect命令都是和spawn開啟的程式進行互動的

interact:允許使用者互動

相關文章