Linux腳本中有很多場景是進行遠程操作的,例如遠程登錄ssh、遠程復制scp、文件傳輸sftp等。這些命令中都會涉及到安全密碼的輸入,正常使用命令時是需要人工手動輸入密碼並接受安全驗證的。為了實現自動化遠程操作,我們可以借用expect的功能。
expect是一個免費的編程工具語言,用來實現自動和交互式任務進行通信,而無需人的干預。expect是不斷發展的,隨着時間的流逝,其功能越來越強大,已經成為系統管理員的的一個強大助手。expect需要Tcl編程語言的支持,要在系統上運行expect必須首先安裝Tcl。
一、Tcl 安裝
下載地址: http://www.tcl.tk/software/tcltk/downloadnow84.tml
(1)下載源碼包
wget http://nchc.dl.sourceforge.net/sourceforge/tcl/tcl8.4.11-src.tar.gz
(2)解壓縮源碼包
tar xfvz tcl8.4.11-src.tar.gz
(3)安裝配置
cd tcl8.4.11/unix
./configure --prefix=/usr/tcl --enable-shared
make
sudo make install
(4)后續
安裝完畢以后,進入tcl源代碼的根目錄,把子目錄unix下面的tclUnixPort.h copy到子目錄generic中。
注意:暫時不要刪除tcl源代碼,因為expect的安裝過程還需要用。
運行configure報錯
上面在運行configure這一步會報錯:
$ ./configure --prefix=/usr/tcl --enable-shared
...
checking system version (for dynamic loading)... ./configure: 1: ./configure: Syntax error: Unterminated quoted string
這是是configure文件里的一行字符串引號配對錯誤引起的,搜索"/etc/.relid"查找到該行:
system=MP-RAS-`awk '{print }' /etc/.relid'`
處理方式是去掉倒數第2個那個多出來的下引號,本以為去掉之后可以直接執行完,沒想到又有一個錯誤:
checking FIONBIO vs. O_NONBLOCK for nonblocking I/O... ./configure: 1: ./configure: Syntax error: Unterminated quoted string
還是引號配對錯誤引起的錯誤,於是又搜索"/etc/.relid"查找到該行:
system=MP-RAS-`awk '{print }' /etc/.relid‘`
處理方式依舊是去掉多出來的下引號,然后再重新configure就可以了。
二、expect 安裝 (需Tcl的庫)
(1)下載源碼包
wget http://sourceforge.net/projects/expect/files/Expect/5.45/expect5.45.tar.gz/download
(2)解壓縮源碼包
tar xzvf download
注意:下載的是download這個壓縮包,而不是expect5.45.tar
.gz。
(3)安裝配置
cd expect5.45
./configure --prefix=/usr/expect --with-tcl=/usr/tcl/lib --with-tclinclude=../tcl8.4.11/generic
make
sudo make install
ln -s /usr/tcl/bin/expect /usr/expect/bin/expect
三、expect 腳本命令
expect的核心是spawn、expect、send、set。
spawn 調用要執行的命令
- expect 等待命令提示信息的出現,也就是捕捉用戶輸入的提示:
- send 發送需要交互的值,替代了用戶手動輸入內容
- set 設置變量值
- interact 執行完成后保持交互狀態,把控制權交給控制台,這個時候就可以手工操作了。如果沒有這一句登錄完成后會退出,而不是留在遠程終端上。
- expect eof 這個一定要加,與spawn對應表示捕獲終端輸出信息終止,類似於if....endif
expect腳本必須以interact或expect eof結束,執行自動化任務通常expect eof就夠了。
其他設置
- 設置expect永不超時 set timeout -1
- 設置expect 300秒超時,如果超過300沒有expect內容出現,則退出 set timeout 300
expect編寫語法
expect使用的是tcl語法
- 一條Tcl命令由空格分割的單詞組成. 其中, 第一個單詞是命令名稱, 其余的是命令參數
cmd arg arg arg
- $符號代表變量的值. 在本例中, 變量名稱是foo.
$foo
- 方括號執行了一個嵌套命令. 例如, 如果你想傳遞一個命令的結果作為另外一個命令的參數, 那么你使用這個符號
[cmd arg]
- 雙引號把詞組標記為命令的一個參數. "$"符號和方括號在雙引號內仍被解釋
"some stuff"
- 大括號也把詞組標記為命令的一個參數. 但是, 其他符號在大括號內不被解釋
{some stuff}
- 反斜線符號是用來引用特殊符號. 例如:n 代表換行. 反斜線符號也被用來關閉"$"符號, 引號,方括號和大括號的特殊含義
四、expect腳本自動獲取root權限
運行下面的expect腳本,可以在不手動輸入密碼的情況下,自動獲取root權限:
#!/usr/expect/bin/expect -f
set timeout=5 #設置5秒超時
#下面幾行后面不能添加注釋,否則會異常
#send "exit\r" - exit命令:會退出root賬號,成為普通用戶
spawn su - root
expect "密碼:"
send "zlkj\r"
send "pwd\r"
#send "exit\r"
interact #使用interact后,腳本將退出到root賬號下,可以手動執行root權限的命令
exit 0 #退出腳本
運行腳本,效果如下:
zlkj@zlkj:~$ ./test.sh
spawn su - root
密碼:
root@zlkj:~# pwd
/root
root@zlkj:~#
可以看到,在退出腳本后,切換到了root用戶。