兩種Linux下非互動式命令的實現
一、概述
在Linux環境,有多種實現自動化的指令碼語言,如Shell、Python、Perl、Tcl等。Shell語言因與Shell外殼結合緊密,是最常見的實現自動化的指令碼語言。
同時,在Linux環境中存在大量功能單一的小工具——通常它們在指定輸入後,立即就可獲得輸出,例如echo、cat等字串/文字列印工具,又或者是如sed、awk等最常用的字串編輯工具。通過編寫Shell指令碼,我們可以反覆利用這些小工具來實現一些自動化的批處理。
在少數情況下,我們也需要用到一些互動式的工具,例如passwd、fdisk等——這意味著在自動化執行的過程中,我們必須停頓下來,滿足工具本身的互動式流程。本文將介紹兩種在使用互動式命令時規避互動來實現自動化的方式。
二、用分界符控制互動式命令
Shell中的 ‘<<’符號表示一種特殊的重定向,用於向某一個命令傳遞多行輸入。當指令碼中出現此符號時,Shell將首先會把緊跟著‘<<’的一個字串,視為一種特殊的分界符;然後,使用者可以輸入一連串的資料;最後,使用者單獨起一行,用另一個相同的分界符結尾。在兩個分界符之間的內容,都被視為命令的輸入引數。
我們在實際的軟體開發專案中看到最多的就是用cat向一個檔案輸入一段文字。例如下面的example1.sh指令碼中的內容:
cat > example1.sql <<EOFSQL
declare @num int, @sql nvarchar(1000)
set @sql='select @a=count(*) from tableName '
exec sp_executesql @sql,N'@a int output',@num output
select @num
<<EOFSQL
該指令碼的執行結果是生成一個example1.sql檔案,內容為兩個分界符EOFSQL之間所示的內容。
用cat命令向一個文字輸入字串,本身不是互動式的。當使用互動式命令時,分界符便可以控制命令的輸入引數,滿足不同的控制流的要求。
三、用expect命令控制多個命令
在執行另外一些操作(如ssh登入)時,我們無法用分界符的方法來輸入多個命令,因為ssh的輸入來源是終端(分界符的輸入,應理解為通常意義上的字串)。這時,我們可以考慮用expect命令。
expect命令是Linux中專門以非互動式方法處理互動式命令的工具。相比分界符來說,它更為強大,且能實現分界符能實現的一切功能。
expect命令的工作原理是在shell中另啟一個新程序,並且在此程序中模擬了終端,對輸入/輸出進行全面監控。而要使用expect命令,則必須需要編寫獨立的指令碼。
expect有相當多的引數和語法,下面我們僅介紹一些基礎部分,供大家參考。
1.[#! /usr/bin/expect]
expect指令碼的第一行總是用這個語法。這類似於shell指令碼的#! /bin/sh,這句話的含義也是定義指令碼的直譯器。
值得注意的是,根據作業系統的不同,expect命令的位置也可能是在 /usr/local/bin/expect。使用前,使用者應確認工具是否存在(確認方法是在root使用者下執行“which expect”命令)。
2.[set timeout 30]
設定響應的超時時間,計時單位是秒。設定timeout -1表示永不超時。
3.[spawn ssh -l username ip]
spawn是進入expect環境後才可以執行的expect內部命令。它主要的功能是給ssh執行程序加個殼,用來傳遞互動指令。
4.[expect "xxxxx:"]
這裡的expect也是一個內部命令。這個命令的意思是判斷上次輸出結果裡是否包含“xxxxx:”的特定字串,如果有則立即返回。
expect還有些擴充套件的用法,最常見的如下所示:
expect {
“xxx1” {command1;exp_continue}
“xxx2” {command 2}
}
以上程式碼的含義如同C語言的switch語句,不同的條件類似不同的case子句。而其中的exp_continue就如同不加break語句,程式將繼續執行後面的語句。
5.[send "ispass\r"]
這是執行互動動作,即模擬終端進行輸入。值得注意的是,命令字串結尾別忘記加上“\r”。
6.[expect eof]
退出expect直譯器 。
下面是一個使用expect命令的例項:
#! /usr/bin/expect -f
set timeout -1
spawn ssh -l zhou 10.10.10.10
expect {
"yes/no" { send "yes\r";exp_continue}
"*assword:" {send "zhou"}
}
expect "*>" {send "echo’HelloWorld!’\r"}
expect "*>" {send"exit\r"}
expect eof
示例中,我們通過ssh以使用者zhou登入了10.10.10.10,然後向ssh輸入該使用者的密碼。登入成功之後,我們列印“Hello World!”,之後退出ssh,結束expect命令的執行。
expect命令的更詳細用法請參考man手冊。
四、總結
本文簡單地介紹了在Linux下,兩種使用互動式命令時規避互動來實現自動化的方式,供相關的開發人員參考。
-----------------
本人微信公眾號:zhouzxi,請掃描以下二維碼: