expect


一 expect介紹

expect是一個免費的編程工具,用來實現自動的交互式任務,而無需人為干預。說白了,expect就是一套用來實現自動交互功能的軟件。需要安裝

yum install -y expect

expect基礎

在使用expect時,基本上都是和以下四個命令打交道:

命令   	作用
spawn 	 啟動新的進程
expect	 從進程接收字符串
send	 用於向進程發送字符串
interact 允許用戶交互
  • spawn命令用來啟動新的進程,spawn后的expectsend命令都是和使用spawn啟動的新進程進行交互。
  • expect通常用來等待一個進程的反饋,我們根據進程的反饋,再使用send命令發送對應的交互命令。
  • send命令接收一個字符串參數,並將該參數發送到進程。
  • interact命令用的其實不是很多,一般情況下使用spawnexpectsend和命令就可以很好的完成我們的任務;但在一些特殊場合下還是需要使用interact命令的,interact命令主要用於退出自動化,進入人工交互。比如我們使用spawnsendexpect命令完成了ftp登陸主機,執行下載文件任務,但是我們希望在文件下載結束以后,仍然可以停留在ftp命令行狀態,以便手動的執行后續命令,此時使用interact命令就可以很好的完成這個任務。

總結expect自動應答的基本步驟

第一步: 運行一個程序或命令=>  spawn 命令信息
第二步: 識別產生信息關鍵字=>  expect 捕獲關鍵字   {send  應答信息}
第三步: 根據識別關鍵做處理=>  send  應答信息

二 expect實例

自動應答腳本

#!/usr/bin/expect

spawn ssh root@192.168.12.20 uptime

expect "yes/no"
send "yes\n"

expect "*assword"
send "1\n"

expect eof

解釋

#1、#!/usr/bin/expect -f:使用expect來解釋該腳本

#2、spwan:
spawn是進入expect環境后才可以執行的expect內部命令,如果沒有裝expect或者直接在默認的SHELL下執行是找不到spawn命令的。它主要的功能是給ssh運行進程加個殼,用來傳遞交互指令;

#3、expect:
expect "*assword":這里的expect也是expect的一個內部命令,這個命令的意思是判斷上次輸出結果里是否包含“password”的字符串,如果有則立即返回;否則就等待一段時間后返回,這里等待時長就是前面設置的30秒;

#4、send:
send "1\n":當匹配到對應的輸出結果時,就發送密碼到打開的ssh進程,執行交互動作;

首次登陸之后,再次登陸,就不會出現yes/no的提示了,所以上述腳本再次運行會出現spawn 命令出現交互式提問的expect 匹配不上的情況,此時腳本會阻塞在原地,我們可以set timeout 3設置超時時間,單位為秒,默認情況下是10秒,以保障腳本超時則結束,

#!/usr/bin/expect -f

spawn ssh root@192.168.12.20 uptime

set timeout 3  # 某一條expect語句在原地匹配,超過了3秒,無論是否匹配成功都會繼續執行下一條指令

expect "yes/no"
send "yes\n"

expect "*assword"
send "1\n"

expect eof

設置超時時間的目的僅僅只是為了讓腳本不要一直卡在原地,要真正解決上述問題,需要改寫成下述形式

#!/usr/bin/expect -f

spawn ssh root@192.168.12.20 hostname

# 注意
# 1、{}一定要換行
# 2、下述語句就一個expect,代表匹配了一次,會匹配完一行就匹配下一行
expect {
    "yes/no" {send "yes\r";exp_continue}
    "*assword" {send "1\n"}
}

expect eof

練習

[root@aliyun ~]# cat 1.sh 
#!/usr/bin/expect -f

spawn ssh egon@127.0.0.1

set timeout -1  # 設置為-1代表永不超時,如果expect沒有捕捉到就一直停在原地

expect {
"yes/no" {send "yes\n"} 
}

expect {
"password" {send "1\n"}
}

expect "*egon*"
send "ls\n"

expect "\$"
send "pwd\n"

expect "\$"
send "exit\n"  # 注意一定要輸入exit結束信號

expect eof  # 最后關閉匹配
[root@aliyun ~]# 

interact交互

interact:執行完成后保持交互狀態,把控制權交給控制台,這個時候就可以手工操作了。如果沒有這一句登錄完成后會退出,而不是留在遠程終端上。

[root@egon ~]# cat test.sh 
#!/usr/bin/expect -f

spawn ssh root@192.168.12.20

expect {
    "yes/no" {send "yes\r";exp_continue}
    "*assword" {send "1\n"}
}

interact
[root@egon ~]# 
[root@egon ~]# ./test.sh 
spawn ssh root@192.168.12.20
root@192.168.12.20's password: 
Last login: Wed Aug 26 21:28:04 2020 from egon
+--------------------------------------------+
|                                            |
|    你當前登錄的是支付業務后台數據庫服務    |
|    請不要刪庫                              |
|                                            |
+--------------------------------------------+
[root@egon ~]# pwd
/root
[root@egon ~]# echo "hello"
hello
[root@egon ~]# exit
登出
Connection to 192.168.12.20 closed.
[root@egon ~]# 

三 為expect腳本傳參

shell腳本中的變量無法直接在expect中使用的,若expect需要使用變量

一方面可以自己定義

#!/usr/bin/expect -f

set timeout -1
set user "root"
set ip "192.168.12.20"
set cmd "hostname"
set pass "1"


spawn ssh $user@$ip $cmd

expect {
    "yes/no" {send "yes\r";exp_continue}
    "*assword" {send "$pass\n"}
}

expect eof

另外一方面可以通過下述方式引入shell變量,注意此時解釋器換成#!/bin/bash

#!/bin/bash

user="root"
ip="192.168.12.20"
cmd="hostname"
pass="1"

expect << EOF
spawn ssh $user@$ip $cmd

expect {
    "yes/no" {send "yes\r";exp_continue}
    "*assword" {send "$pass\n"}
}

expect eof
EOF

此外,expect腳本還可以從命令行獲取參數

在expect中,$argc表示參數個數,而參數值存放在$argv中,比如取第一個參數就是[lindex $argv 0],以此類推。

[root@egon ~]# cat test.sh 
#!/usr/bin/expect -f

if {$argc != 4} {
    puts "Usage:./script.sh <ip> <username> <password> <cmd>"
    exit 1
}

set ip [lindex $argv 0]
set user [lindex $argv 1]
set pass [lindex $argv 2]
set cmd [lindex $argv 3]
set timeout -1

spawn ssh $user@$ip $cmd

expect {
    "yes/no" {send "yes\r";exp_continue}
    "*assword" {send "$pass\n"}
}

expect eof
[root@egon ~]# ./test.sh 
Usage:./script.sh <ip> <username> <password> <cmd>
[root@egon ~]# ./test.sh 192.168.12.20 root 1 hostname
spawn ssh root@192.168.12.20 hostname
root@192.168.12.20's password: 
egon

能夠在工作中熟練的使用Shell腳本就可以很大程度的提高工作效率,如果再搭配上expect,那么很多工作都可以自動化進行,對工作的展開如虎添翼。如果你會Python的話,你的視野將會更加開闊,那個時候你又會“嫌棄”expect了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM