1. 程式人生 > 其它 >免互動

免互動

技術標籤:筆記linuxshell

免互動

Here Document 免互動

使用I/O重定向的方式將命令列表提供給互動式程式,標準輸入的一種替代品

語法格式:

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

標記

注意事項

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

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

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

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

Hi
EOF
echo $i

通過 passwd 給使用者設定密碼
passwd lisi <<EOF

abc1234 #這兩行是輸入的密碼和確認密碼
abc1234
EOF

變數替換

file="EOF1.txt"
i="school"
cat > $file <<EOF
I am going to $i
EOF

cat EOF1.txt

整體賦值給變數

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

echo $myvar

關閉變數替換的功能

var="Great! I am going to school!"
myvar=$(cat <<'EOF'			#對標記加單引號,即可關閉變數替換			 
This is Line 1.
Today is Monday.
$var
EOF
)

echo $myvar

去掉每行之前的 TAB 字元或者空格

#!/bin/bash
var="Great! I am going to school!"
myvar=$(cat <<-'EOF'			#對標記前加“-”,即可抑制各行首TAB或空格			 
	This is Line 1.
 Today is Monday.
$var
EOF
)

echo $myvar

多行註釋

#!/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指令碼中互動相關的問題
rpm -q expect
rpm -q tcl
yum install -y expect

基本命令:

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

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

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

(4)send
向程序傳送字串,用於模擬使用者的輸入;該命令不能自動回車換行,一般要加\r(回車)或者\n
例:
case1="密碼"
respond="abc1234"

expect "$case1" {send "$respond1\r"}		#同一行send部分要有{}

expect "$case1"	
send "$response1\r"							#換行send部分不需要有{}

expect					#只要匹配了其中一個情況,執行相應的send語句後退出該expect語句
{
"$case1" {send "$response1\r"}
"$case2" {send "$response2\r"}
"$case3" {send "$response3\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 語句。
例如:下例將判斷互動輸出中是否存在 yes/no 或 *assword。如果匹配 yes/no 則輸出 yes 並再次執行判斷;如果匹配 *assword 則輸出 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 $argv 1]		相當於 password=$2


expect直接執行
#!/usr/bin/expect

#設定超時時間
set timeout 60

#引數傳入
set hostname [lindex $argv 0]
set password [lindex $argv 1]
#追蹤命令
spawn ssh [email protected]$hostname
#免互動執行,捕捉資訊並匹配
expect {
	"(yes/no)"
	{send "yes\r"; exp_continue}
	"*password"
	{send "$password\r"}
}
#把控制權交給控制檯
interact


嵌入執行
#!/bin/bash
hostname=$1
password=$2

/usr/bin/expect <<-EOF 		#expect 開始標誌
spawn ssh [email protected]${hostname}

expect {
"(yes/no)"
{send "yes\r";exp_continue}
"*password"
{send "$password\r"}
}

expect "*]#"
send "exit\r"
expect eof
EOF


建立使用者並設定密碼
#!/bin/bash
user=$1
password=$2
#非互動命令放在expect外面
useradd $user
#開始免交換執行
/usr/bin/expect <<EOF
spawn passwd $user 			#開啟一個程序跟蹤 passwd 命令,expect 只能捕捉該程序資訊

expect "新的*" 				
send "${password}\r" 		
expect "重新*" 	
send "${password}\r" 		
expect eof				
EOF


實現 ssh 自動登入
#!/usr/bin/expect
set timeout 5
set hostname [lindex $argv 0]
set password [lindex $argv 1]

spawn ssh $hostname
expect {
	"Connection refused" exit					#連線失敗情況,比如對方ssh服務關閉
	"Name or service not known" exit			#找不到伺服器,比如輸入的IP地址不正確
	"to continue" {send "yes\r";exp_continue}
	"password:" {send "$password\r"}
}

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


建立磁碟分割槽並格式化
還可使用echo再標準輸入

方法一:

#!/bin/bash
NEWDEV=`ls /dev/sd*|grep -o '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

方法二:

fdisk /dev/$VAR < fd.txt

方法三:

echo "n
	p
	
	
	
	w"  | fdisk /dev/$VAR