1. 程式人生 > >【expect】使用心得

【expect】使用心得

一、expect的安裝

expect是在tcl的基礎上發展起來的,所以在安裝expect之前要先安裝tcl。

(一)tcl安裝

tcl下載地址:

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  
make install

注意:
1、安裝完畢以後,進入tcl原始碼的根目錄,把子目錄unix下面的tclUnixPort.h copy到子目錄generic中。

2、暫時不要刪除tcl原始碼,因為expect的安裝過程還需要用。

(二)安裝expect(需tcl的庫)

1.下載原始碼包

wget http://sourceforge.net/projects/expect/files/Expect/5.45/expect5.45.tar.gz/download  

2.解壓縮原始碼包

tar xzvf expect5.45.tar.gz  

3.安裝配置

    cd expect5.45  
    .
/configure --prefix=/usr/expect --with-tcl=/usr/tcl/lib --with-tclinclude=../tcl8.4.11/generic make make install ln -s /usr/tcl/bin/expect /usr/expect/bin/expect

二、expect的簡要說明

我們通過Shell可以實現簡單的控制流功能,如:迴圈、判斷等。但是對於需要互動的場合則必須通過人工來干預,有時候我們可能會需要實現和互動程式如telnet伺服器等進行互動的功能。而Expect就使用來實現這種功能的工具。

三、expect的簡單用法

(一)expect基礎概念

1. [#!/usr/bin/expect] 

這一行告訴作業系統腳本里的程式碼使用那一個shell來執行。這裡的expect其實和linux下的bash、windows下的cmd是一類東西。 這一行需要在指令碼的第一行。

2. [set timeout 30] 

設定超時時間,計時單位為:秒 ,timeout -1 為永不超時

3. [spawn ssh -l username 192.168.1.1] 

spawn是進入expect環境後才可以執行的expect內部命令,如果沒有裝expect或者直接在預設的SHELL下執行是找不到spawn命令的。所以不要用 “which spawn“之類的命令去找spawn命令。好比windows裡的dir就是一個內部命令,這個命令由shell自帶,你無法找到一個dir.com 或 dir.exe 的可執行檔案。

它主要的功能是給ssh執行程序加個殼,用來傳遞互動指令。

4. [expect "password:"] 

這裡的expect也是expect的一個內部命令,expect的shell命令和內部命令是一樣的,但不是一個功能,習慣就好了。這個命令的意思是判斷上次輸出結果裡是否包含“password:”的字串,如果有則立即返回,否則就等待一段時間後返回,這裡等待時長就是前面設定的timeout

5. [send "ispass\r"] 

這裡就是執行互動動作,與手工輸入密碼的動作等效。

溫馨提示: 命令字串結尾別忘記加上“\r”,如果出現異常等待的狀態可以核查一下。

6. [interact] 

執行完成後保持互動狀態,把控制權交給控制檯,這個時候就可以手工操作了。如果沒有這一句登入完成後會退出,而不是留在遠端終端上。如果你只是登入過去執行

7.$argv 引數陣列

expect指令碼可以接受從bash傳遞過來的引數.可以使用[lindex $argv n]獲得,n從0開始,分別表示第一個,第二個,第三個….引數

(二)expect簡單用法

    #!/usr/bin/expect -f
    set timeout 60      #設定超時時間
    log_file test.log   #設定指令碼日誌
    log_user 1                   #是否顯示指令碼輸出資訊 1代表顯示,0代表不顯示
    set hostname [lindex argv 0] #接收第一個引數
    set password [lindex argv 1]
    spawn ssh root@$hostname     #連線遠端機器
    expect {
           "(yes/no)"               
           {
           send "yes\r"
           expect "*password:" {send "$password\r"}
           }
           "*password"
           {
           send "$password\r"
           }
    }
    send "echo ==\$(rpm -qa | grep mariadb)==\r"
    expect -re "==.*==.*==(.*)=="
    set mariadb $expect_out(1,string)
    expect "*]#"
    send "rpm -e --nodeps $mariadb\r"
    expect "*]#"
    send "exit\r"
    expect eof

上述程式碼即為一個簡單的expect指令碼,登入到遠端機器並解除安裝mariadb,expect中最常用的就是”expect”和“send”命令。
expect “pattern”
send “command\r”
當遠端機出現了匹配”pattern”的字串,就執行”command”命令,在執行完命令之後別忘了加上回車符,如此便可實現自動輸入密碼等一系列功能。

四、shell巢狀expect

    #!/bin/bash
    hostname=$1                #接收第一個引數
    password=$2
    /usr/bin/expect <<-EOF    # 重定向到expect
    spawn ssh root@${hostname}
    expect {
            "(yes/no)"
            {
            send "yes\r"
            expect "*assword:" {send "$password\r"}
            }
            "*assword"
            {
            send "$password\r"
            }
    }
    expect "*]#"
    send "echo 'export MAVEN_HOME=/usr/local/maven' >> /etc/profile\r"
    send "echo 'export M2_HOME=\\\$MAVEN_HOME' >> /etc/profile\r"
    send "echo 'export PATH=\\\$PATH:\\\$MAVEN_HOME/bin' >> /etc/profile\r"
    expect "*]#"
    send "source /etc/profile\r"
    expect "*]#"
    send "exit\r"
    expect eof
    EOF               #結束重定向

五、expect常見問題

1、expect指令碼中source命令不起作用?

shell指令碼中巢狀expect指令碼,再編寫source命令即可正常使用

2、shell巢狀expect指令碼中$expect_out(1,string)無法獲得匹配字串?

單純使用expect指令碼即可正常獲取

3、shell巢狀expect指令碼中對字元轉義需要三個反斜槓,expect指令碼中對字元轉義只需要一個反斜槓。