expect簡單教程


一、概述

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。

二、工作原理

從最簡單的層次來說,Expect的工作方式象一個通用化的Chat腳本工具。Chat腳本最早用於UUCP網絡內,以用來實現計算機之間需要建立連接時進行特定的登錄會話的自動化。
Chat腳本由一系列 expect-send對組成:
expect等待輸出中輸出特定的字符,通常是一個提示符,如果等到了就使用send發送特定的響應例如下面我們使用expect-send對來模擬一遍用戶名和密碼的交互式輸入
# expect等待標准輸出中出現"Login:"字符串,如果等到了"Login:"字符串,就使用send回應somebody(其中\n用於模擬敲回車)
expect "Login:"
send "somebody\n"

# expect等待"Password:",使用send回應111111
expect "Password:"
send "111111\n"
上述幾條語句描述出了Expect最簡單的腳本操作模式。

三、應用

3.1自動登陸ssh服務器

使用expect實現自動登錄的腳本,網上有很多,可是都沒有一個明白的說明,初學者一般都是照抄、收藏。可是為什么要這么寫卻不知其然。本文用一個最短的例子說明腳本的原理。

#!/usr/bin/expect
set timeout 30
spawn ssh test@127.0.0.1
expect "password:"
send "123456\n"
interact
1. [#!/usr/bin/expect]    
這一行告訴操作系統腳本里的代碼使用那一個shell來執行。這里的expect其實和linux下的bash、windows下的cmd是一類東西。  
注意:這一行需要在腳本的第一行。
2. [set timeout 30]  
設置超時時間,單位是秒;expect超時等待的時間。默認timeout為10s。  
3. [spawn ssh test@127.0.0.1]  
spawn是進入expect環境后才可以執行的expect內部命令,如果沒有裝expect或者直接在shell下執行是找不到spawn命令的。這個就好比cd是shell的內建命令,離開shell,就無法執行cd一樣。 它主要的功能是給ssh運行進程加個殼,用來傳遞交互指令。  
4. [expect "password:"]    
這里的expect也是Expect腳本語言的一個內部命令。在shell下輸入expect,會進入expect的工作界面,這個expect是一個shell命令,而[expect "password:"] 中的expect只是一個跟expect腳本名同名的一個內建命令。這個命令的意思是判斷上次輸出結果里是否包含“password:”的字符串,如果有則立即返回,向下執行;否則就一直等待,直到超時時間到,就是2里的30秒。
5. [send "123456\n"]  
這里就是執行交互動作,與手工輸入密碼的動作等效。效果上跟用戶手動在終端上輸入123456之后敲一個回車一樣。
6. [interact]  
執行完成上述命令后保持在交互狀態,此時Expect會把控制權交給控制台,這個時候就變回手工操作,Expect已經執行完成。如果沒有這一句登錄完成后會立刻退出,而不是留在遠程終端上。如果你只是登錄過去執行一段命令就退出,可將其改為[expect eof]
該腳本執行現象如下:
gyl@gyl:~$ ./test.exp 
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語句實現上傳下載的自動交互

#!/usr/bin/expect

#
#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
該腳本仿照C語言的命令行參數,用到switch-case語句,if-else語句,功能算是比較全面了。該腳本規定了有4種使用方法,不符合使用要求時給出相應提示。其中上傳和下載每種操作含有加dstpath和不含dstpath,共4種;
autoscp -down srcpath dstpath #srcpath基於服務器用戶主目錄,dstpath基於本地當前目錄
autoscp -down srcpath        #等價於autoscp -down srcpath .
autoscp -up srcpath dstpath    #srcpath基於本地當前目錄,dstpath基於服務器用戶主目錄
autoscp -up srcpath        #等價於autoscp -up srcpath ~
NOTE:因為該腳本使用scp的上傳下載功能,當操作打文件時,耗時較久,如果timeout值過小,超時時間一到,數據傳輸就會終止,程序退出。因此timeout值應該根據文件大小做適當調整。

四、參考資料






免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM