Linux – Expect

測試環境為 CentOS 7 x86_64 虛擬機

Expect 可以預先編寫與 Linux shell 的終端視窗 (當前的行程 process) 所顯示的字串來產生相對應的動作.跟 TeraTerm 的 Macro 類似 – http://benjr.tw/20386

須先安裝 expect 套件.

[root@localhost ~]# yum install expect

直接來看一個範例:
當使用者輸入 Hi 或是 How are you 會回應相對應的字串,然後繼續執行,除非是輸入 Bye 才會返回 terminal,如果使用者鍵盤在10秒內沒有輸入任何值時也會返回 terminal (重置超時計時器 timeout 10 秒).

[root@localhost ~]# cat test.exp 
#!/usr/bin/expect 
set timeout 10
expect {
      "Hi" {send "Hi\n"; exp_continue}
      "How are you?" {send "Fine\n"; exp_continue}
      "Bye" {send "Bye Bye\n"; exit}
}

參數說明:

  • timeout – 如果使用者鍵盤或是其他程式執行沒有產生任何值,預設等待時間為 10秒即結束,可以使用 -1 代表沒有中斷時間.
  • expect – 等待指定的 patterns 出現在 terminal (當前的行程 process) 上(使用者輸入或是其他程式執行時產生).
  • send – 將字串發送到當 terminal (當前的行程 process) 上.
  • exp_continue – 會繼續執行而不是返回 terminal (當前的行程 process),預設會重置超時計時器 timeout .
  • exit – 退出 expect .

實際測試可以看到當使用者輸入 Hi 或是 How are you 會回應相對應的字串,然後繼續執行,最後輸入 Bye 才會返回 terminal.

[root@localhost ~]# chmod a+x test.exp
[root@localhost ~]# ./test.exp
Hi
Hi
How are you
Fine
Bye
bye bye

自動登入 SSH

在 Linux 環境下使用 SSH 進行遠端連線,需要輸入密碼,除了可以透過把公鑰匯出 http://benjr.tw/301 或是透過指令 sshpass – http://benjr.tw/8287 ,另外一種方式就是透過 expect

下面範例使用 expect 透過遠端 ssh (免輸入密碼) 來執行指令.

[root@localhost ~]# vi ssh.exp
#!/usr/bin/expect
set timeout 10
set HOST [lindex $argv 0]
set USER [lindex $argv 1]
set PASS [lindex $argv 2]

spawn ssh -o StrictHostKeyChecking=no $USER@$HOST
expect {
        "password:" {send "$PASS\r"}
}
interact

參數說明:

  • timeout – 如果使用者鍵盤或是其他程式執行沒有產生任何值,預設等待時間為 10秒即結束,可以使用 -1 代表沒有中斷時間.
  • expect – 等待指定的 patterns 出現在 terminal (當前的行程 process) 上(使用者輸入或是其他程式執行時產生).
  • send – 將字串發送到當 terminal (當前的行程 process) 上.
  • $argv 0,1,2 – 執行 expect 後面所接的命令行參數.
  • spawn – 產生新的行程 (process).
  • interact – 把目前行程 (process)的控制權交還給使用者.

指令說明:

  • ssh -o StrictHostKeyChecking=no $USER@$HOST
    在 SSH Client 第一次登入時 SSH Server 會詢問是否接收公開金鑰 (SSH Client 需要輸入 yes),使用參數 StrictHostKeyChecking no 讓預設都為接受.
[root@localhost ~]# chmod a+x ssh.exp 
[root@localhost ~]# ./ssh.exp 192.168.95.205 root 111111 
spawn ssh -o StrictHostKeyChecking=no root@192.168.95.205
root@192.168.95.205's password: 
Last login: Fri Jan 18 18:18:16 2019 from 192.168.95.205
[root@localhost ~]# exit
logout
Connection to 192.168.95.205 closed.
[root@localhost ~]# 

使用 autoexpect 來產生 exp 檔

還有一種方式可以更簡單完成,只需要透過 autoexpect 來記錄並產新相對應的 exp 檔.

自動登入 SSH 執行 hostname 後結束.

[root@localhost ~]# autoexpect -f autossh.exp ssh root@192.168.95.205
autoexpect started, file is autossh.exp
root@192.168.95.205's password: 
Last login: Fri Jan 18 18:29:37 2019 from 192.168.95.205
[root@localhost ~]# hostname -a
localhost.localdomain localhost4 localhost4.localdomain4 localhost.localdomain localhost6 localhost6.localdomain6
[root@localhost ~]# exit
logout
Connection to 192.168.95.205 closed.
autoexpect done, file is autossh.exp

不過紀錄得太詳細了,可能還需要修改後才能使用.

set timeout -1
spawn ssh root@192.168.95.205
match_max 100000
expect -exact "root@192.168.95.205's password: "
send -- "111111\r"
expect -exact "\r
Last login: Fri Jan 18 18:29:37 2019 from 192.168.95.205\r\r
^[\]0;root@localhost:~^G^[\[?1034h\[root@localhost ~\]# "
send -- "hostname -a\r"
expect -exact "hostname -a\r
localhost.localdomain localhost4 localhost4.localdomain4 localhost.localdomain localhost6 localhost6.localdomain6\r
^[\]0;root@localhost:~^G\[root@localhost ~\]# "
send -- "exit\r"
expect eof

修改後的內容:

set timeout -1
spawn ssh root@192.168.95.205
match_max 100000
expect -exact "root@192.168.95.205's password: "
send -- "111111\r"
expect "#"
send -- "hostname -a\r"
expect "#"
send -- "exit\r"
expect eof

參數說明:

  • timeout – 如果使用者鍵盤或是其他程式執行沒有產生任何值,預設等待時間為 10秒即結束,可以使用 -1 代表沒有中斷時間.
  • spawn – 產生新的行程 (process).
  • match_max – defines the size of the buffer (in bytes) used internally by expect.
  • expect – 等待指定的 patterns 出現在 terminal (當前的行程 process) 上(使用者輸入或是其他程式執行時產生).
  • send – 將字串發送到當 terminal (當前的行程 process) 上.
  • eof – The corresponding body is executed upon end-of-file.
[root@localhost ~]# ./autossh.exp 
spawn ssh root@192.168.95.205
root@192.168.95.205's password: 
Last login: Fri Jan 18 19:06:33 2019 from 192.168.95.205
[root@localhost ~]# hostname -a
localhost.localdomain localhost4 localhost4.localdomain4 localhost.localdomain localhost6 localhost6.localdomain6
[root@localhost ~]# exit
logout
Connection to 192.168.95.205 closed.
沒有解決問題,試試搜尋本站其他內容

發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *

這個網站採用 Akismet 服務減少垃圾留言。進一步瞭解 Akismet 如何處理網站訪客的留言資料