一、概述
expect是Unix系統中用來進行自動化控制和測試的軟件工具,由Don Libes制作,作為Tcl腳本語言的一個擴展,應用在交互式軟件中如telnet,ftp,Passwd,fsck,rlogin,tip,ssh等等。該工具利用Unix偽終端包裝其子進程,允許任意程序通過終端接入進行自動化控制;也可利用Tk工具,將交互程序包裝在X11的圖形用戶界面中。
我們通過Shell可以實現簡單的控制流功能,如:循環、判斷等。但是對於需要交互的場合則必須通過人工來干預,比如普通用戶使用sudo命令時就需要我們手動輸入密碼;expect就是能夠完成這種自動交互任務,而無需人的干預。Expect的作者Don Libes在1990年開始編寫Expect時對Expect做有如下定義:Expect是一個用來實現自動交互功能的軟件套件(Expect [is a] software suite for automating interactive tools)。系統管理員可以使用它創建用來實現對命令或程序提供輸入的腳本:一般來說這些輸入都需要手工輸入(比如之前提到的執行sudo程序期望用戶從終端輸入用戶密碼)進行的,Expect則可以根據程序的提示 模擬標准輸入給程序提供信息來實現交互程序執行。甚至可以實現簡單的BBS聊天機器人。
Expect是不斷發展的,隨着時間的流逝,其功能越來越強大,已經成為系統管理員的的一個強大助手。Expect需要Tcl編程語言的支持,要在系統上運行Expect必須首先安裝Tcl。
二、工作原理
Chat腳本由一系列 expect-send對組成:
expect "Login:"
send "somebody\n"
# expect等待"Password:",使用send回應111111
expect "Password:"
send "111111\n"
三、應用
3.1自動登陸ssh服務器
使用expect實現自動登錄的腳本,網上有很多,可是都沒有一個明白的說明,初學者一般都是照抄、收藏。可是為什么要這么寫卻不知其然。本文用一個最短的例子說明腳本的原理。
set timeout 30
spawn ssh test@127.0.0.1
expect "password:"
send "123456\n"
interact
spawn ssh test@127.0.0.1
test@127.0.0.1 's password:
Linux gyl 2.6.32-46-generic #108-Ubuntu SMP Thu Apr 11 15:55:01 UTC 2013 i686 GNU/Linux
Ubuntu 10.04.4 LTS
Welcome to Ubuntu!
* Documentation: https://help.ubuntu.com/
New release 'precise ' available.
Run 'do-release-upgrade ' to upgrade to it.
Last login: Sat May 11 01:08:19 2013 from localhost
$
3.2封裝scp語句實現上傳下載的自動交互
#
#auto down/up files from/to server over scp.protocol
#Usage:
# autoscp -down srcpath (the same as autoscp -down srcpath .)
# autoscp -down srcpath dstpath (dstpath is based on $pwd)
# autoscp -up srcpath (the same as autoscp -up srcpath ~)
# autoscp -up srcpath dstpath (dstpath is based on ~ on the server)
#
set timeout 100
set cmd [lindex $argv0]
set option [lindex $argv 0]
set srcpath [lindex $argv 1]
set dstpath [lindex $argv 2]
#parse command number
switch -- $argc {
2 {
set dstpath .
}
3 {
}
default {
send_user "Usage:$cmd option srcpath \[dstpath\]\n"
exit
}
}
#parse command and do it.
if {$option=="-down"} {
spawn scp -r gyl@127.0.0.1:/home/gyl/$srcpath $dstpath
} else {
if {$option=="-up"} {
spawn scp -r $srcpath gyl@127.0.0.1:/home/gyl/$dstpath
} else {
send_user "bad arg:\"$option\"\n"
exit
}
}
#autofill infomation
expect "password:"
send "123456\n"
#exit
expect eof
autoscp -down srcpath #等價於autoscp -down srcpath .
autoscp -up srcpath dstpath #srcpath基於本地當前目錄,dstpath基於服務器用戶主目錄
autoscp -up srcpath #等價於autoscp -up srcpath ~