expect不完全使用指南

expect介紹

expect是一個自動交互功能的工具。expect命令會新建一個子進程,通過spawn來執行shell腳本,監測腳本的返回結果,然後通過expect判斷要進行的交互輸入內容。

藉助Expect處理交互的命令,可以將交互 過程如:ssh登錄,ftp登錄等寫在一個腳本上,使之自動化完成.尤其適用於需 要對多臺服務器執行相同操作的環境中,可以大大提高系統管理人員的工作效率 。

expect安裝

Expect是一個基於TCL開發出的語言包。系統一般不會自帶,需要自行安裝。

TCL(Tool Command Language)工具腳本語言,是Linux內的一種語言包。

系統爲RHEL/CentOS:

yum install expect

系統爲Debian/Ubuntu:

apt-get install expect

expect腳本

expect腳本以#!/usr/bin/expect開頭,用來告訴操作系統腳本里的代碼使用那一個shell來執行。這裏的expectlinux下的bashwindows下的cmd是一類東西。

以.exp或者.ex結束,通過./xxx.exp運行(需要可執行權限),類似bash腳本。

也可以以sh結尾,通過expect ./xx.sh執行,如expect ./auto_deploy.sh

expect 命令選項

​expect [選項] [ -c cmds ] [ [ -[f|b] ] cmdfile ] [ args ] 

​ 選項

  • -v:顯示expect版本信息。

  • -f:從文件讀取命令,僅用於使用#!時。如果文件名爲file,則從stdin讀取(使用./file從文件名爲file的文件讀取)。

  • -c:從命令行執行expect腳本,默認expect是交互地執行的,如下所示:

    expect -c 'expect "\n" {send "pressed enter\n"}
    

    如果你執行了上面的腳本,它會等待輸入換行符\n。按enter鍵以後,它會打印出pressed enter這個消息,然後退出。

  • -i:使用-i選項,可以通過來自於標準輸入的讀命令來交互地執行expect腳本。如下所示:

    expect -i arg1 arg2 arg3
    expect1.1>set argv
    arg1 arg2 arg3
    expect1.2>
    

    正常情況下,當你執行上面的expect命令的時候(沒有-i選項),它會把arg1當成腳本的文件名,所以-i選項可以讓腳本把多個參數當成一個連續的列表。

  • -d:可以輸出輸出調試信息

    $ cat sample.exp
    # !/usr/bin/expect -f
    expect “\n”;
    send “pressed enter”;
    
    $ expect -d sample.exp
    expect version 5.43.0
    argv[0] = expect argv[1] = -d argv[2] = sample.exp
    set argc 0
    set argv0 “sample.exp”
    set argv “”
    executing commands from command file sample.exp
    
    expect: does “” (spawn_id exp0) match glob pattern “\n”? no
    
    expect: does “\n” (spawn_id exp0) match glob pattern “\n”? yes
    expect: set expect_out(0,string) “\n”
    expect: set expect_out(spawn_id) “exp0”
    expect: set expect_out(buffer) “\n”
    send: sending “pressed enter” to { exp0 pressed enter}
    
  • -b: 通常,expect會在執行腳本之前,把整個腳本都讀入到內存中。-b選項可以讓expect一次只讀取腳本中的一行。當你沒有寫完整個腳本的時候,這是十分有用的,expect可以開始執行這個不完整的腳本。

    expect -b
    
  • -d:讓expect不解釋命令行參數

    你可以使用標識符讓expect不解釋命令行參數。你可以像下面這樣的讀入命令行參數:

    $ cat print_cmdline_args.exp
    #!/usr/bin/expect
    puts ‘argv0 : [lindex $argv 0];
    puts ‘argv1 : [lindex $argv 1];
    

    當執行上面的腳本的時候,會跳過命令行選項,它們會被當成參數(而不是expect選項),如下所示:

    $ expect print_cmdline_args.exp -d -c
    argv0 : -d
    argv1 : -c
    

expect內置命令

  • set timeout: 設置超時時間的,單位是:秒 。例如:set timeout 30

    # 永遠等待,不會超時
    set timeout -1  
    
  • spawnspawn是進入expect環境後纔可以執行的expect內部命令,如果沒有裝expect或者直接在默認的SHELL下執行是找不到spawn命令的。所以不要用 which spawn之類的命令去找spawn命令。spawn用來啓動新的進程的,spawn後的sendexpect命令都是和spawn打開的進程進行交互的。

    # 直接運行一個 bash 腳本
    spawn /mnt/sh_expect.sh
    # 直接運行一個 bash 命令
    spawn ssh -p ${port} $user@$host
    
  • send:用於向進程發送命令字符串 ,這裏就是執行交互動作,與手工輸入的動作等效。 命令字符串結尾別忘記加上\n

  • expectexpect也是expect的一個內部命令,expectshell命令和內部命令是一樣的,但不是一個功能。這個命令的意思是判斷上次輸出結果裏是否包含指定的字符串,如果有則立即返回,否則就等待一段時間後返回,這裏等待時長就是set timeout xxx 設置的時間。

    # 從標準輸入中等到hi和換行鍵後,向標準輸出輸出hello there
    expect "hi\n"
    send "hello there!\n"
    # 退出 spawn 會話,返回當前的shell進程
    send "exit\n"
    # 退出expect
    expect eof
    
  • interact:從自動交互狀態退出到輸入狀態,由用戶完成剩餘的操作.,這個時候就可以手工操作了。如果沒有這一句登錄完成後會退出,而不是留在遠程終端上。

  • exp_continue:重置set timeout設置的時間,重新執行當前expect分支

    # 如果匹配到*assword,那麼發送密碼,並進入下面的expect語句(uname -a語句)。
    # 如果匹配到yes/no,那麼發送yes,並重新執行這個expect分支語句。
    expect {
        "*assword" {send "123456\r";}
        "yes/no" {send "yes\r";exp_continue}
    }  
    

命令行參數

$argc$argv 0,$argv 1 ... $argv n  

argc表示命令行參數個數,後面分別表示各個參數項,0表示第一個參數,1表示第二個參數,以此類推,可以通過lindex獲取對應參數值[lrange $argv 0 0]

if {$argc < 2} {
	puts stdout "$argv0 err params\n"
	exit 1
}
set user [lindex $argv 0]
set password [lindex $argv 1]

參數存在argv 當中,[lrange $argv 0 0]表示第1個參數,[lrange $argv 0 4]爲第一個到第五個參數。如果需要計算的話必須用expr,如計算2-1,則必須用[expr 2-1]

語法

expect遵循tcl的語法規範,基礎語法部分可以查看這裏,循環、條件判斷、各種運算符都有詳細的說明

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章