1. 程式人生 > 其它 >Here Document免互動和Expect自動化互動

Here Document免互動和Expect自動化互動

Here Document免互動和Expect自動化互動

一、Here Document免互動

1、Here Document 免互動概述

  • 使用I/0重定向的方式將命令列表提供給互動式程式或命令,比如ftp、cat或read命令
  • 是標準輸入的一種替代品可以幫助指令碼開發人員不必使用臨時檔案來構建輸入資訊,而是直接就地生產出一個“檔案"並用作“命令”的標準輸入
  • Here Document 也可以與非互動式程式和命令一起使用

2、語法格式

命令  <<標記
...
內容         #  標記之間是傳入內容
... 
標記

3、注意事項

  • 標記可以使用任意合法字元(通常為EOF)
  • 結尾的標記一定要頂格寫, 前而不能有任何字元
  • 結尾的標記後面也不能有任何字元( 包括空格)
  • 開頭標記前後的空格會被省略掉

4、免互動的各種用法

(1)、免互動方式實現對行數的統計,將要統計的內容置於標記“EOF”之間,直接將內容傳給wc -l 來統計

wc -l <<EOF
>Line1
>Line2
>EOF

(2) 通過read命令接收輸入並列印,輸入值是兩個EOF 標記之間的部分,作為變數i的值

read i <<EOF
>Hi
>EOF
echo $i

(3)通過passwd給使用者設定密碼

passwd list <<EOF
>abc123123 >abc123123 EOF

(4)支援變數替換

在寫入檔案時會先將變數替換成實際值,再結合cat 命令完成寫入

#!/bin/bash
file="eof1.txt"
i="school"
cat > $file <<EOF
I am going to $i
EOF

注:一次性輸出兩行內容的方法

echo 123 > test.txt
echo 123 >> test.txt    # 通過重定向追加


echo -e "abc\nabc"  > test.txt         #  使用\n追加

cat 
<<EOF > test.txt #使用免互動的方式新增 tee test.txt <<EOF # tee:相當於重定向標準輸出的命令,效果相當於cat命令,不光將內容輸出至檔案當中,還輸入至螢幕中

(5)整體賦值給變數,然後通過echo命令將變數值打印出來

#!/bin/bash
var="Great! I am going to school!"
myvar=$(cat <<EOF
This is Line 1.
Today is Monday.
$var
EOF
)
echo $myvar

6、關閉變數替換的功能,按照字元原本的樣子輸出,不做任何修改或替換

#!/bin/bash
var="Great! I am going to school!"
myvar=$(cat <<'EOF'     # 對EOF新增單引號,則相當於關閉替換功能
This is Line 1.
Today is Monday.
$var
EOF
)

echo $myvar

(7)去掉每行之前的TAB字元

#!/bin/bash
var="Great! I am going to school!"
myvar=$(cat <<-'EOF'        #在標記前加“-”,即可抑制各行tab字元
       This is Line 1.
       Today is Monay.
       $var
EOF
)
echo "$myvar"

(7)多行註釋

  • Bash的預設註釋是“#”,該註釋方法只支援單行註釋: Here Document 的引入解決了多行註釋的問題
  • “:"代表什麼都不做的空命令。中間標記區域的內容不會被執行,會被bash忽略掉,因此可達到批量註釋的效果
#!/bin/bash
var="Great! I am going to school!"
: <<-EOF   #多行註釋,“:”開頭的Here Document標記內容不會被執行
      This is Line 1.
   Today is Monday.
  $var
EOF

echo "abcd"

二、Expect

  • 建立在tcl語言基礎上的一個工具,常被用於進行自動化控制和測試,解決shell指令碼中互動相關的問題。
  • 使用expect得先進行 expect包的安裝
rpm -q expect
rpm -q tcl
yum -y install expect

1、基本命令

(1)指令碼直譯器

  • expect指令碼中首先引入檔案,表明使用的是哪一個shell
#!/usr/bin/expect

(2)spawn

  • spawn後面通常跟一個Linux執行命令,表示開啟一個會話、啟動程序,並追蹤後續互動資訊。

例:

spawn passwd root

(3)expect

  • 判斷上次輸入結果中是否包含指定的字串,如果有則立即返回,否則就等待超時時間後返回:只能捕捉由spawn啟動的程序的輸出;
  • 用於接收命令執行後的輸出,然後和期望的字串匹配

(4)send

  • 向程序傳送字串,用於模擬使用者的輸入;該命令不能自動回車換行。一般要加\r(回車)或者\n
例:
方式一:
expect "密碼" {send "abc123\r"}   # 同一行send部分要有{}

方式二:
expect "密碼"
send "abc123\r"    #  換行send部分不需要有{}

方式三:
expect支援多個分支

expect {       # 只要匹配了其中一個情況,執行相應的send語句後退出該expect語句
"密碼1" {send "abc123\r"}
"密碼2" {send "123456\r"}
"密碼3" {send "123123\r"}
}

(5)結束符

expect eof
  • 表示互動結束,等待執行結束,退回到原使用者,與spawn對應
  • 比如切換到root使用者,expect指令碼預設的是等待10s當執行完命令後,預設停留10s後,自動切回了原使用者

interact

  • 執行完成後保持互動狀態,把控制權交給控制檯,會停留在目標終端而不會退回到原終端,這個時候就可以手工操作了,interact後的命令不起作用; 比如interact後新增exit,並不會退出root使用者。而如果沒有interact則登入完成後會退出,而不是留在遠端終端上。
  • 使用interact會保持在終端而不會退回到原終端; 比如切換到root使用者,會一直在root使用者狀態下:比如ssh到另一伺服器,會一直在目標伺服器終端,而不會切回的原伺服器

注意: expect eof 與 interact 只能二選一

(6)set

  • expect預設的超時時間是10秒,通過set命令可以設定會話超時時間,若不限制超時時間則應設定為-1
例: set timeout 30

(7)exp_continue

  • exp_ continue 附加於某個expect 判斷項之後,可以使該項被匹配後,還能繼續匹配該expect判斷語句內的其他項exp_ continue 類似於控制語句中的continue 語句。表示允許expect 繼續向下執行指令
例如:下例將判斷互動輸出中是否存在yes/no 或*password。 如果匹配yes/no 則輸出yes並再次執行判斷:如果匹配*password
則輸出abc123 並結束該段expect語句

expect{
   "(yes/no)”{send "yes\r"; exp_continue; }
   "*password" {set timeout 300; send "abc123\r"; }
 }

注意:使用exp_ continue時,如果跟蹤像passwd 這樣的輸入密碼後就結束程序的命令,expect{}外不要 再加上expect eof,因為spawn程序結束後會預設向expect傳送eof,,會導致後面的expect eof 執行報錯

(8) send_ user

  • send_ user 表示回顯命令,相當於echo

(9)接收引數

  • expect指令碼可以接受從bash命令列傳遞的引數,使用[lindex $argv n] 獲得。其中n從0開始,分別表示第一一個, 第二個,第三個…引數。

例:
set hostname [lindex $argv 0]   相當於hostname=$1
set password [lindex Sargv 1]   相當於password=$2

2、Expect 直接執行,需要使用expect命令去執行指令碼

(1)su切換使用者

#! /usr/bin/expect
#設定超時時間
set timeout 5

(2)引數傳入

set username  [lindex $argv 0]
set password [lindex $argv 1]

#開始追蹤命令 spawn su $username
#免互動執行,捕捉資訊並匹配 expect
"密碼" send "Spassword\r" expect "*]#" send user "ok" .
#把控制權交給控制檯 interact #expect eof

3、嵌入執行模式,將expect過程融入shell當中,方便執行和處理

(1)建立使用者並設定密碼

#! /bin/bash
user=$1
password=$2
#非互動命令放在expect外面
useradd $user
#開始免交換執行
/usr/bin/expect <<-EOF
#expect開始標誌
spawn passwd $user
#開啟-一個程序跟蹤passwd命令,expect只能捕捉該程序資訊
expect "新的*"
send "$ {password}\r" .
expect "重新*"
send "$ {password} \r"
expect eof
EOF

(2)實現ssh自動登入

#!/usr/bin/expect
set timeout 5
set hostname [lindex $argv 0]
set password [lindex $argv 1]

spawn ssh Shos tname
expect {
  "Connection refused" exit
  #連線失敗情況,比如對方ssh服務關閉
  "No route to host" exit
   #找不到伺服器,比如輸入的IP地址不正確
  "(yes/no)”{send "yes\r";exp_continue }
  "password:" { send "$password\r"}
} 

interact
exit    #interact後的命令不起作用

(3)建立磁碟分割槽並格式化

可使用echo再標準輸入
方法一:
#!/bin/bash
NEWDEV='ls /dev/sd* Igrep -0 'sd[b-z]' | uniq`
for VAR in $NEWDEV
do
echo -e "n\np\n\n\n\nw\n" | fdisk /dev/$VAR &> /dev/null
done
mkfs.xfs /dev/${VAR}"1" &> /dev/null

方法二:
echo -e "n\np\n\n\n\nw\n" > fd.txt
fdisk /dev/$VAR < fd. txt

方法三:
echo "n
    P

   w"| fdisk /dev/$VAR