用expect命令實現Shell的自動化交互

背景

linux腳本中有不少場景是進行遠程操做的,例如遠程登陸ssh、遠程複製scp、文件傳輸sftp等。這些命令中都會涉及到安全密碼的輸入,正常使用命令時是須要人工手動輸入密碼並接受安全驗證的。爲了實現自動化遠程操做,咱們能夠借用expect的功能。linux

expect

expect的核心是spawn、expect、send、set。安全

spawn 調用要執行的命令

expect 等待命令提示信息的出現,也就是捕捉用戶輸入的提示:
send 發送須要交互的值,替代了用戶手動輸入內容
set 設置變量值
interact 執行完成後保持交互狀態,把控制權交給控制檯,這個時候就能夠手工操做了。若是沒有這一句登陸完成後會退出,而不是留在遠程終端上。
expect eof 這個必定要加,與spawn對應表示捕獲終端輸出信息終止,相似於if....endif服務器

expect腳本必須以interact或expect eof結束,執行自動化任務一般expect eof就夠了。ssh

其餘設置

  • 設置expect永不超時 set timeout -1
  • 設置expect 300秒超時,若是超過300沒有expect內容出現,則退出 set timeout 300

expect編寫語法

expect使用的是tcl語法spa

  • 一條Tcl命令由空格分割的單詞組成. 其中, 第一個單詞是命令名稱, 其他的是命令參數
    cmd arg arg arg
  • $符號表明變量的值. 在本例中, 變量名稱是foo.
    $foo
  • 方括號執行了一個嵌套命令. 例如, 若是你想傳遞一個命令的結果做爲另一個命令的參數, 那麼你使用這個符號
    [cmd arg]
  • 雙引號把詞組標記爲命令的一個參數. "$"符號和方括號在雙引號內仍被解釋
    "some stuff"
  • 大括號也把詞組標記爲命令的一個參數. 可是, 其餘符號在大括號內不被解釋
    {some stuff}
  • 反斜線符號是用來引用特殊符號. 例如:n 表明換行. 反斜線符號也被用來關閉"$"符號, 引號,方括號和大括號的特殊含義

示例

login.exp專用於遠程登陸,快捷使用方式: login.exp "exclude" "${remote_ip}" "${remote_user}" "${remote_passwd}" "${remote_command}"code

#!/usr/bin/expect -f
##########################################################
# 經過SSH登錄和執行命令
#參數:1.Use_Type [check/execute]
#     2.SSHServerIp
#     3.SSHUser
#     4.SSHPassword
#     5.CommandList [多個命令間以;間隔]
#返回值:
#     0  成功
#     1  參數個數不正確
#     2  SSH 服務器服務沒有打開
#     3  SSH 用戶密碼不正確
#     4  鏈接SSH服務器超時
##########################################################

proc usage {} {
    regsub ".*/" $::argv0 "" name
    send_user "Usage:\n"
    send_user "    $name Use_Type SSHServerIp SSHUser SSHPassword CommandList\n"
    exit 1
}
  
## 判斷參數個數
if {[llength $argv] != 5} {
    usage
}

#設置變量值
set Use_Type [lindex $argv 0]
set SSHServerIp [lindex $argv 1]
set SSHUser [lindex $argv 2]
set SSHPassword [lindex $argv 3]
set CommandList [lindex $argv 4]

#spawn ping ${SSHServerIp} -w 5
#expect {
#    -nocase -re "100% packet loss" {
#        send_error "Ping ${SSHServerIp} is unreachable, Please check the IP address.\n"
#        exit 1
#    }
#}

set timeout 360
set resssh 0
#定義變量標記ssh鏈接時是否輸入yes確認
set inputYes 0
set ok_string LOGIN_SUCCESS
if {$Use_Type=="check"} {
    #激活ssh鏈接,若是要須要輸入yes確認,輸入yes,設置inputYes爲1,不然輸入ssh密碼
    spawn ssh ${SSHUser}@${SSHServerIp} "echo $ok_string"
} else {          
    spawn ssh ${SSHUser}@${SSHServerIp} "$CommandList"
}
expect {
    -nocase -re "yes/no" {
        send -- "yes\n"
        set inputYes 1
    }
    -nocase -re "assword: " {
        send -- "${SSHPassword}\n"
        set resssh 1
    }
   #-nocase -re "Last login: " { 
   #     send -- "${CommandList}\n"
   #}
    $ok_string {}
    -nocase -re "Connection refused" {
        send_error "SSH services at ${SSHServerIp} is not active.\n"
        exit 2
    }
    timeout {
        send_error "Connect to SSH server ${SSHUser}@${SSHServerIp} timeout(10s).\n"
        exit 4
    }
}

#若是輸入了yes確認,輸入ssh密碼
if {$inputYes==1} {
    expect {
        -nocase -re "assword: " {
            send -- "${SSHPassword}\n"
            set resssh 1
        }
    }
}

#若是出現try again或者password:提示,說明輸入的用戶密碼錯誤,直接退出。
if {$resssh==1} {
    expect {
        -nocase -re "try again" {
            send_error "SSH user:${SSHUser} passwd error.\n"
            exit 3
        }
        -nocase -re "assword:" {
            send_error "SSH user:${SSHUser} passwd error.\n"
            exit 3
        }
        eof {}
    }
}
send_error -- "$expect_out(buffer)"
#-nocase -re "No such user" {
#        send_error "No such user.\n"
#        exit 5
#    }
#exit
相關文章
相關標籤/搜索