天天看點

Linux expect 用法安裝用法例子

expect是建立在tcl基礎上的一個工具,它用來讓一些需要互動的任務自動化地完成。

因為expect是基于tcl的,是以需要你的系統中安裝有tcl

如何檢查?

[root@dev ~]# whereis tcl

tcl: /usr/lib/tcl8.4 /usr/share/tcl8.4

如果看不到結果,請先安裝tcl

> 安裝tcl

解壓tcl安裝包後

cd tcl8.4.11/unix/

./configure --prefix=/usr/local/tcl/ --enable-shared

make && make install

> 安裝expect

解壓expect安裝包後

cd expect-5.43

./configure --prefix=/usr/local/expect/ --with-tcl=/usr/local/tcl/lib/ --with-tclinclude=/opt/tcl8.4.11/generic/ --enable-shared

注意:指定的/opt/tcl8.4.11/generic/ 為我們上面解壓的tcl目錄

> 建立連接配接符号

ln -s /usr/local/expect/bin/expect /usr/bin/expect

> 檢視連接配接符号

ls -l /usr/bin/expect

lrwxrwxrwx. 1 root root 28 9月   8 11:21 /usr/bin/expect -> /usr/local/expect/bin/expect

這個符号連結将在編寫expect腳本檔案時用到,例如在expect檔案頭部會指定用于執行該腳本的shell 

#!/usr/bin/expect 

> 測試

[root@localhost opt]# expect

expect1.1> exit

[root@localhost opt]# 

這樣就可以開始運作expect腳本了。

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

這一行告訴作業系統腳本裡的代碼使用那一個shell來執行。這裡的expect其實和linux下的bash、windows下的cmd是一類東西。 

注意:這一行需要在腳本的第一行。 

2. [set timeout 30] 

基本上認識英文的都知道這是設定逾時時間的,現在你隻要記住他的計時機關是:秒。timeout -1 為永不逾時,預設情況下,timeout是10秒;

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運作程序加個殼,用來傳遞互動指令。 

spawn後面加上需要執行的shell指令,比如說spawn sudo touch testfile

4. [expect "password:"] 

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

5. [send "ispass\r"] 

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

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

6. [interact] 

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

7. $argv 參數數組

expect腳本可以接受從bash傳遞過來的參數.可以使用[lindex $argv n]獲得,n從0開始,分别表示第一個,第二個,第三個....參數

其中,$argc為指令行參數的個數,$argv0為腳本名字本身,$argv為指令行參數。[lrange $argv 0 0]表示第1個參數,[lrange $argv 0 4]為第一個到第五個參數。與c語言不一樣的地方在于,$argv不包含腳本名字本身。

8. send和send_user

send會将expect腳本中需要的資訊發送給spawn啟動的那個程序,而send_user隻是回顯使用者發出的資訊,類似于shell中的echo而已。

9. 如果你在第一行(#!那行)使用-d (debug參數),可以在運作的時候輸出一些很有用的資訊

比如你會看見

argv[0] = /usr/bin/expect argv[1] = -d argv[2] = ./launch.exp argv[3] = 1 argv[4] = 2 argv[5] = 3

使用這些也可以完成參數傳遞

10. exp_continue的用法

expect {

        -re "permission denied, please try again." {

                send_user "error:permission denied.\n"

                exit

        }

        -re "are you sure you want to continue connecting (yes/no)?" {

                send "yes\r";exp_continue

        -re "assword:" {

                send "$loginpass\r";exp_continue

        -re "connection refused" {

        timeout {

        eof {

}

使用exp_continue後,會重新從目前expect塊的開始重新執行,可以簡單了解問while循環的continue

下面的腳本例子,實作了:登入一個linux伺服器,執行 df -h 等指令

vi expectexample.sh 後輸入下面的腳本内容儲存後,使用chmod +x expectexample.sh 指令為腳本賦予可執行權限。

#!/usr/bin/expect -f

#-------------------------------------------- set the variable,you can modify the value

set ipaddr [lrange $argv 0 0]

set port [lrange $argv 1 1]

set loginuser [lrange $argv 2 2]

set loginpass [lrange $argv 3 3]

set cmd_prompt "]#|~]?"

# 逾時時間,機關(秒)

set timeout 3600

#-------------------------------------------- login by ssh

spawn ssh -p $port $loginuser@$ipaddr

                -re "connection refused" {

                send_user "error:connection refused.\n"

                send "yes\r"

                exp_continue

                send "$loginpass\r"

        -re $cmd_prompt {

                send "\r"

#-------------------------------------------- now,we do some commands

                send "df -h\r"

                send "free -m\r"

                send "uptime\r"

send "cd /opt\r"

send "mkdir shanhy123\r"

send "cd shanhy123\r"

send "echo 123 > 123.txt\r"

send "/opt/xs.sh\r"

send "exit\r"

expect eof

#interact

-------------------------------------------------

其中 xs.sh 為我寫的一個測試的 shell 腳本,裡面故意做了一個sleep 模拟耗時操作,代碼如下:

#!/bin/bash

sleep 10

echo abc > /opt/abc.txt

注意:expect腳本必須以interact或expect eof結束,執行自動化任務通常expect eof就夠了。