1. 程式人生 > 其它 >shell程式設計之免互動

shell程式設計之免互動

目錄:

一、Here Document 免互動

二、Expect

一、Here Document 免互動

使用I/O重定向的方式將命令列表提供給互動式程式或命令, 比如 ftp、cat 或 read 命令。

是標準輸入的一種替代品可以幫助指令碼開發人 員不必使用臨時檔案來構建輸入資訊, 而是直接就地生產出一一個"檔案"並用作"命令"的標準輸入。Here Document 也可 以與非互動式程式和命令一起使用。

語法格式∶

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

注意事項∶

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

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

1  wc -l <<EOF
2 > abc
3 > 123
4 > def
5 > EOF
6 3

通過 passwd 給使用者設定密碼

passwd lisi <<EOF
>abc1234
>abc1234   #這兩行是輸入的密碼與確認密碼
>EOF

1、支援變數替換

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

1 #!/bin/bash
2 
3 file="EOF1.txt"
4 i="school"
5 cat > $file <<EOF
6 I am going to $i
7 EOF
8 
9 cat EOF1.txt

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

 1 #! /bin/bash
 2 var="Great! I am going to school!"
 3 myvar=$(cat <<EOF
 4 This is Line 1.
 5 Today is Monday.
 6 $var
 7 EOF
 8  9 
10
echo "$myvar"

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

 1 #!/bin/bash
 2 
 3 var="Great! I am going to school!"
 4 myvar=$(cat <<'EOF'    #對標記加單引號,即可關閉變數替換
 5 This is Line 1.
 6 Today is Monday .
 7 $var
 8 EOF
 9 10 
11 echo $myvar

4、去掉每行之前的TAB字元

 1 #!/bin/bash
 2 
 3 var="Great! I am going to school!"
 4 myvar-s (cat <<-'EOF'   #在標記前加“-”,即可抑制各行首TAB
 5            This is Line 1.
 6       Today is Monday.
 7    $var
 8 EOF
 9 )
10 
11 echo $myvar

5、多行註釋

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

二、Expect

建立在tcl語言基礎上的一個工具,常被用幹進行自動化控制和測試, 解決shell指令碼中互動相關的問題

rpm -q expect
rpm -q tcl
yum install-y expect

1、基本命令∶

(1)指令碼直譯器

expect 指令碼中首先引入檔案,表明使用的是哪一個 shell。

#!/usr/bin/expect

(2)spawn

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

例∶ spawn passwd root

(3)expect

判斷上次輸出結果中是否包含指定的字串,如果有則立即返回,否則就等待超時時間後返回;

只能捕捉由spawn啟動的程序的輸出;

用於接收命令執行後的輸出, 然後和期望的字串匹配

(4)send

向程序傳送字串,用於模擬使用者的輸入;該命令不能自動回車換行,一般要加\r (回車)或者\n

 1 例:
 2 方式一:
 3 expect "密碼" {send "abc123\r"}
 4 #同一行send部分要有{}
 5 
 6 方式二:
 7 expect "密碼"
 8 send "abc123\r"
 9 #換行send部分不需要有{}
10 
11 方式三:
12 expect支援多個分支
13 
14 expect { #只要匹配了其中一個情況,執行相應的send語句後退出該expect語句
15 "密碼1" {send "abc123\r"}
16 "密碼2" {send "123456\r"}
17 "密碼3" {send "123123\r"}
18 }

(5)結束符

1,expect eof

表示互動結束,等待執行結束,退回到原使用者,與spawn對應。

比如切換到root使用者,expect指令碼預設的是等待10s,當執行完命令後,預設停留10s後,自動切回了原使用者

2,interact

執行完成後保持互動狀態,把控制權交給控制檯,會停留在目標終端而不會退回到原終端,這個時候就可以手工操作 了,interac t後的命令不起作用,比如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 繼續向下執行指令

1 例如:下例將判斷互動輸出中是否存在yes/no 或*password。 如果匹配yes/no 則輸出yes並再次執行判斷:如果匹配*password
2 則輸出abc123 並結束該段expect語句
3 
4 expect{
5    "(yes/no)”{send "yes\r"; exp_continue; }
6    "*password" {set timeout 300; send "abc123\r"; }
7  }

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

(8)send_ user

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

(9)接收引數

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

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

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

su切換使用者

 1 #!/usr/bin/expect
 2 
 3 #設定超時時間
 4 set timeout 5
 5 
 6 #引數傳入
 7 set username [lindex $argv 0] 
 8 set password [lindex $argv 1]
 9 
10 #開始追蹤命令
11 spawn su $username
12 
13 #免互動執行,捕捉資訊並匹配
14 expect "密碼"
15 send "$password\r"
16 expect "*]#"
17 send_user "ok"
18 
19 #把控制權交給控制檯
20 interact
21 #expect eof

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

建立使用者並設定密碼

 1 #!/bin/bash
 2 user=$1
 3 password=$2
 4 
 5 #非互動命令放在expect外面
 6 useradd $user
 7 
 8 #開始免交換執行
 9 /usr/bin/expect <<-EOF
10 #expect開始標誌
11 spawn passwd $user
12 #開啟一個程序跟蹤passwd命令,expect 只能捕捉該程序資訊
13 
14 expect "新的*"
15 send "${password}\r"
16 expect "重新*"
17 send "${password}\r"
18 expect eof
19 EOF

3、實現ssh自動登入

 1 #!/usr/bin/expect
 2 set timeout 5
 3 set hostname [lindex $argv 0]
 4 set password [lindex $argv 1]
 5 
 6 spawn ssh Shos tname
 7 expect {
 8   "Connection refused" exit
 9   #連線失敗情況,比如對方ssh服務關閉
10   "No route to host" exit
11    #找不到伺服器,比如輸入的IP地址不正確
12   "(yes/no)”{send "yes\r";exp_continue }
13   "password:" { send "$password\r"}
14 } 
15 
16 interact
17 exit    #interact後的命令不起作用

4、建立磁碟分割槽

 1 #!/bin/bash
 2 
 3 /usr/bin/expect <<EOF
 4 spawn fdisk /dev/sdb
 5 
 6 expect "(輸入 m 獲取幫助):"
 7 send "n\n"
 8 expect " (default p):"
 9 send "p\r"
10 expect "(1-4,預設 1):"
11 send "\r"
12 expect "起始 扇區"
13 send "\r"
14 expect "Last 扇區"
15 send "+6G\r"
16 expect "命令"
17 send "w\r"
18 
19 expect eof
20 EOF
21 
22 echo "Creating a successful"