1. 程式人生 > 其它 >Blog.042 Shell 程式設計 免互動

Blog.042 Shell 程式設計 免互動

本章目錄

1. Here Document 免互動
  1.1 概述
  1.2 語法格式
  1.3 用法例項
2. Except 工具
  2.1 概述
  2.2 基本命令
  2.3 模擬使用者輸入字串
  2.4 結束符
  2.5 用法例項

1. Here Document 免互動


  1.1 概述

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


  1.2 語法格式

1 命令 <<標記  
2 ...
3 內容              #標記之間是傳入內容
4 ...
5 標記

    注意事項:

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


  1.3 用法例項

  • 實現對行數的統計
1 wc -l <<EOF
2 >Line1
3 >Line2
4 >EOF
  • 通過read命令接收輸入並列印兩個EOF標記之間的內容
1 read i <<EOF
2 >Hello 3 >EOF 4 >echo $i
  • 通過passwd給使用者設定密碼
1 passwd zs <<EOF
2 >abc123               #這兩行是輸入密碼和確認密碼
3 >abc123
4 >>EOF
  • 支援變數替換
1 在寫入檔案時會先將變數替換成實際值,再結合cat命令完成寫入
2 #!/bin/bash
3 file="EOF1.txt"
4 i="Home"
5 cat > $file <<EOF
6 I am going $i
7 EOF
  • 整體賦值給變數,通過echo命令加印出來
1 #!/bin/bash
2 var="Great! NG is coming to pc"
3 myvar=$(cat <<EOF
4 Today is Monday
5 $var
6 EOF
7 )
  • 關閉變數替換功能,原樣輸出字元
1 #!/bin/bash
2 var="Great! NG is coming to pc"
3 myvar=$(cat <<'EOF'
4 Today is Monday
5 $var
6 EOF
7 )
  • 去掉每行之前的TAB字元
1 -EOF        #抑制TAB字元輸出
  • 多行註釋
1 Bash的預設註釋是"#",該註釋方法只支援單行註釋;Here Document的引入解決了多行註釋的問題;
2 ":"代表什麼都不做的空命令。中間標記區域的內容不會被執行,會被bash忽略掉,因此可達到批量註釋的效果。
3 
4 :<<EOF             #註釋

2. Except 工具


  2.1 概述

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

1 rpm -q expect
2 rpm -q tcl
3 yum install -y expect

  2.2 基本命令

    (1)指令碼編輯器

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

    (2)spawn

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


    (3)except

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


  2.3 模擬使用者輸入字串

  • 方法一
1 expect "密碼" {send "abc123\r"}                同一行send部分要有{}
  • 方法二
1 expect "密碼" 
2 send "abc123\r"                                換行時不需要加{}
  • 方法三
1 expect     #只要匹配了其中一個情況,執行相應的send語句後退出該expect語句
2 {
3 "密碼1" {send "abc123\r"}
4 "密碼2" {send "123456\r"}
5 "密碼3" {send "123123\r"}
6 }

  2.4 結束符

    (1)except eof

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


    (2)interact

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


    (3)set

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

    (4)exp_continue

  • exp_continue 附加於某個 expect 判斷項之後,可以使該項被匹配後,還能繼續匹配該 expect 判斷語句內的其他項。
  • exp_continue 類似於控制語句中的 continue 語句。表示允許 expect 繼續向下執行指令。
1 expect {
2     "(yes/no)" {send "yes\r"; exp_continue;}          若匹配到yes/no字元,則輸出yes及回車鍵確定
3     "*password" {send "abc123\r";}                    若匹配到password字元,則輸出密碼abc123及回車鍵確定
4 }

    (5)接收引數

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

  2.5 用法例項

  • except 指令碼直接執行
1 #!/usr/bin/expect   
2 set timeout 5
3 set username [lindex $argv 0]    
4 set password [lindex $argv 1]
5 spawn su $username
6 expect "密碼" {send "{$password}\r"}
7 expect "*]#"
8 send "su success!"
9 expect eof
  • 嵌入執行模式
 1 #!/bin/bash
 2 user=$1
 3 password=$2
 4 useradd $user
 5 /usr/bin/expect <<-EOF
 6 spawn passwd $user
 7 expect "新的*"
 8 send "${password}\r"
 9 expect "重新*"
10 send "${password}\r"
11 expect eof
12 EOF
  • 實現 ssh 自動登入,except 直接執行
 1 #!/usr/bin/expect   
 2 set host [lindex $argv 0]
 3 set passwd [lindex $argv 1]
 4 spawn ssh $host
 5 expect {
 6 "Connection refused" exit     
 7 "No route to host" exit       
 8 "(yes/no)" {send "yes\r"; exp_continue}   
 9 "*password:" {send "${passwd}\r"}        
10 }
11 interact
  • 實現 ssh 自動登入,內嵌式
 1 #!/bin/bash
 2 username=$1
 3 passwd=$2
 4 /usr/bin/expect<<-EOF
 5 spawn ssh $username
 6 expect {
 7 "Connection refused" exit
 8 "No route to host" exit
 9 "(yes/no)" {send "yes\r";exp_contiune}
10 "password:" {send "$passwd\r"}
11 }
12 expect eof
13 EOF
  • 免互動建立磁碟
 1 #!/bin/bash
 2 disk=$1
 3 /usr/bin/expect <<-EOF
 4 spawn fdisk $disk
 5 expect "命令" {send "n\r"}
 6 expect "Select" {send "\r"}
 7 expect "分割槽" {send "\r"}
 8 expect "起始" {send "\r"}
 9 expect "Last" {send "\r"}
10 expect "命令(輸入 m 獲取幫助):" {send "w\r"}
11 expect eof
12 EOF
13 partprobe $disk
14 mkfs.xfs $disk -f &> /dev/null
15 if [ $? -eq 0 ]
16 then
17 echo "finsh"
18 mount $disk /mnt
19 else
20 echo "fail"
21 fi

-