1. 程式人生 > >兩種Linux下非互動式命令的實現

兩種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”   {command1exp_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,請掃描以下二維碼: