本文主要講解Shell腳本開發中Expect自動化交互式程序的應用實踐linux
目錄:正則表達式
1.Expect介紹shell
2.安裝Expect軟件和簡單實現交互功能編程
3.Expect程序自動交互的重要命令及實踐數組
4.Expect程序變量介紹bash
5.Expect程序中的if條件語句服務器
一:Expect介紹運維
1)什麼是Expectssh
Expect是一個用來實現自動交互功能的軟件套件,是基於TCL的腳本編程工具語言,方便學習,功能強大。ide
2)爲何要使用Expect
在現今的企業運維中,自動化運維已經成爲運維的主流趨勢,可是在不少狀況下,執行系統命令或程序時,系統會以交互式的形式要求運維人員輸入指定的字符串,以後才能繼續執行命令。例如,爲用戶設置密碼時,通常狀況下就須要手工輸入2次密碼。
[root@aliyun shuzu]# passwd ming66 Changing password for user ming66. New password: BAD PASSWORD: it is WAY too short BAD PASSWORD: is too simple Retype new password: passwd: all authentication tokens updated successfully.
簡單來講,Expect就是用來自動實現與交互式程序通訊的,而無需管理員的手工干預。好比SSH、FTP遠程鏈接等,正常狀況下都須要手工與它們進行交互,而使用Expect就能夠模擬手工交互的過程,實現自動與遠端程序的交互,從而達到自動化運維的目的。
如下是Expect的自動交互工做流程簡單說明,依次執行以下操做:
spawn啓動指定進程——>expect獲取期待的關鍵字——>send向指定進程發送指定字符——>進程執行完畢,退出結束
二:安裝Expect軟件和簡單實現交互功能
準備好兩臺實驗虛擬機,IP地址爲192.168.1.7和192.168.1.8 並設置好yum源,安裝Expect安裝包
[root@aliyun ~]# yum install expect -y [root@aliyun ~]# ifconfig |grep 'inet addr:'|awk -F "[ :]" '{print $13}' 192.168.1.7 127.0.0.1 [root@aliyun ~]# ssh -p22 root@192.168.1.8 The authenticity of host '192.168.1.8 (192.168.1.8)' can't be established. RSA key fingerprint is c8:f2:9e:53:55:98:37:10:31:8f:1a:62:9a:58:c7:8e. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added '192.168.1.8' (RSA) to the list of known hosts. root@192.168.1.8's password: Last login: Sat Jun 9 03:31:56 2018 from 192.168.1.11 [root@aliyun ~]# ifconfig |grep 'inet addr:' |awk -F "[ :]" '{print $13}' 192.168.1.8 127.0.0.1 [root@aliyun ~]# exit logout Connection to 192.168.1.8 closed. [root@aliyun ~]# ssh -p22 root@192.168.1.8 root@192.168.1.8's password: Last login: Sat Jun 9 03:37:29 2018 from 192.168.1.7
能夠看到,每次都須要手工輸入密碼,才能執行ssh命令,不然沒法執行
下面就用Expect的功能實現自動交互,發送密碼並執行上訴ssh命令
[root@aliyun ~]# cat ywxi.exp #!/usr/bin/expect #腳本開頭解析器,和shell相似,表示程序使用expect解析 spawn ssh root@192.168.1.8 uptime #執行ssh命令(注意開頭必需要有spawn,不然沒法實現交互) expect "*password" #利用expect獲取執行上述ssh命令輸出的字符串是否爲期待的字符串*.password,這裏的*是通配符 send "123456\n" #當獲取到期待的字符串*password時,則發送123456密碼給系統,\n爲換行 expect eof #處理完畢後結束Expect
#執行expect腳本
[root@aliyun ~]# which expect /usr/bin/expect [root@aliyun ~]# expect ywxi.exp spawn ssh root@192.168.1.8 uptime root@192.168.1.8's password: 03:46:18 up 16 min, 3 users, load average: 0.00, 0.02, 0.06 [root@aliyun ~]# expect ywxi.exp spawn ssh root@192.168.1.8 uptime root@192.168.1.8's password: 03:46:30 up 16 min, 3 users, load average: 0.00, 0.02, 0.06
三:Expect程序自動交互的重要命令及實踐
Expect程序中的命令是Expect的核心
1)spawn命令
在Expect自動交互程序執行的過程當中,spawn命令是一開始就須要使用的命令,經過spawn執行一個命令或程序,以後全部的Expect操做都會在這個執行過的命令或程序進程中進行,包括自動交互功能,所以若是沒有spawn命令,Expect程序將沒法實現自動交互。因此使用spawn命令是Expect程序實現自動交互工做流程中的第一步,也是最關鍵的一步
apawn命令的語法爲:
spawn [ 選項 ] [ 須要自動交互的命令或程序 ] 選項: -open 表示啓動文件進程 -ignore 表示忽略某些信號
例如:
spawn ssh root@192.168.1.8 uptime
2)expect命令
expect命令的做用就是獲取spawn命令執行後的信息,看看是否和其事先指定的相匹配,一旦匹配上指定的內容就執行expect後面的動做,expect命令也有一些選項,相對用得較多的是-re,表示使用正則表達式的方式來匹配。
expect命令的語法爲:
expect 表達式 [ 動做 ]
例如:
spawn ssh root@192.168.1.8 uptime expect "*password"
注:上述命令不能直接在linux命令行中執行,須要放入expect腳本中執行
expect命令實踐
範例1:執行ssh命令遠程獲取服務器負載值,並要求實現自動輸入密碼
法1:將expect和send放在一行 [root@aliyun ~]# cat ywxi.exp #!/usr/bin/expect spawn ssh root@192.168.1.8 uptime expect "*password" {send "123456\n"} expect eof 執行結果: [root@aliyun ~]# expect ywxi.exp spawn ssh root@192.168.1.8 uptime root@192.168.1.8's password: 04:06:30 up 36 min, 3 users, load average: 0.00, 0.00, 0.00 法2:將expect和send不放在一行 [root@aliyun ~]# cat ywxi.exp #!/usr/bin/expect spawn ssh root@192.168.1.8 uptime expect "*password" send "123456\n" expect eof 執行結果: [root@aliyun ~]# expect ywxi.exp spawn ssh root@192.168.1.8 uptime root@192.168.1.8's password: 04:07:52 up 37 min, 3 users, load average: 0.00, 0.00, 0.00
範例2:利用expect響應shell腳本中的多個read讀入
腳本前準備: [root@aliyun pratice]# cat readex.sh #!/bin/bash read -p 'please input your username:' name read -p 'please input your password:' pass read -p 'please input your email:' email echo -n "you name is $name," echo -n "you password is $pass," echo -n "you email is $email." [root@aliyun pratice]# sh readex.sh please input your username:ywxi please input your password:123456 please input your email:1031664140@qq.com you name is ywxi,you password is 123456,you email is 1031664140@qq.com. expect腳本以下: [root@aliyun pratice]# cat expe.exp #/usr/bin/expect spawn /bin/sh readex.sh #這裏在一個目錄下,用的相對路徑 expect { "username" {exp_send "ywxi\r";exp_continue} #若獲取到的是username信息,則自動輸入ywxi "*pass*" {send "123456\r";exp_continue} #若獲取到的是*pass*信息,則自動輸入123456 "*mail*" {exp_send "1031664140@qq.com\r"} #若獲取到的是*mail*信息,則自動輸入郵件地址 } expect eof 執行結果以下: [root@aliyun pratice]# expect expe.exp spawn /bin/sh readex.sh please input your username:ywxi please input your password:123456 please input your email:1031664140@qq.com you name is ywxi,you password is 123456,you email is 1031664140@qq.com.
3)send命令
exp_send和send命令的使用方法,這兩個命令是expect中的動做命令,用法相似,即在expect命令匹配指定的字符串後,發送指定的字符串給系統,這些命令能夠支持一些特殊轉義符號,例如: \r表示回車、\n表示換行、\t表示製表符等。
send命令有幾個可用的參數,具體以下:
-i : 指定spawn_id,用來向不一樣的spawn_id進程發送命令,是進行多程序控制的參數
-s: s表明slowly,即控制發送的速度,使用的時候要與expect中的變量send_slow相關聯
4)exp_continue命令
這個命令通常處於expect命令中,屬於一種動做命令,通常用在匹配屢次字符串的動做中,從命令的拼寫就能夠看出命令的做用,即讓Expect程序繼續匹配的意思。
使用示例以下:
[root@aliyun pratice]# cat expe.exp #/usr/bin/expect spawn /bin/sh readex.sh expect { "username" {exp_send "ywxi\r";exp_continue} "*pass*" {exp_send "123456\r";exp_continue} "*mail*" {exp_send "1031664140@qq.com\r"} } expect eof
5)send_user命令
send_user命令可用來打印Expect腳本信息,相似shell裏的echo命令,而默認的send、exp_send命令都是將字符串輸出到Expect程序中去。
示例以下:
[root@aliyun pratice]# cat send.exp #!/usr/bin/expect send_user "I am ywxi.\n" #\n表示換行 send_user "I am linuxer,\t" #\t表示Tab鍵 [root@aliyun pratice]# expect send.exp I am ywxi. I am linuxer, [root@aliyun pratice]
四:Expect程序變量介紹
1)普通變量
Expect中的變量定義、使用方法與TCL語言中的變量基本相同
定義變量的基本語法以下:
set 變量名 變量值
示例以下:
set password 「123456」
打印變量的基本語法以下:
puts $變量名
範例:定義及輸出變量
[root@aliyun pratice]# cat bl.exp #!/usr/bin/expect set password "123456" puts $password send_user "$password\n" #send_user 也能夠打印輸出 [root@aliyun pratice]# expect bl.exp 123456 123456
2)特殊參數變量
在Expect裏也有與shell腳本里的$0、$一、$#等相似的特殊參數變量,用於接收及控制Expect腳本傳參。
在Expect中$argv表示參數數組,可使用 [ index $argv n ] 接收Expect腳本傳參,n從0開始,分別表示第一個 [ index $argv 0 ]參數、第二個 [ index $argv 1 ] 參數、第三個[ index $argv 2 ] 參數。
範例:定義及輸出特殊參數變量
[root@aliyun pratice]# cat var.exp #!/usr/bin/expect set file [lindex $argv 0] set host [lindex $argv 1] set dir [lindex $argv 2] send_user "$file\t$host\t$dir\n" puts "$file\t$host\t$dir\n" 執行結果以下: [root@aliyun pratice]# expect var.exp ywxi 192.168.1.7 /etc ywxi 192.168.1.7 /etc ywxi 192.168.1.7 /etc
Expect接收參數的方式和bash腳本的方式有些區別,bash是經過$0...$n這種方式來接收的,而Expect是經過set<變量名稱>[lindex $argv <param index>]來接收的,例如set file [lindex $argv 0]
除了基本的位置參數外,Expect也支持其餘的特殊參數,例如:$argc表示傳參的個數,$argv0表示腳本的名字。
範例:針對Expect腳本傳參的個數及腳本名參數的實踐
[root@aliyun pratice]# cat var.exp #!/usr/bin/expect set file [lindex $argv 0] set host [lindex $argv 1] set dir [lindex $argv 2] puts "$file\t$host\t$dir" puts $argc puts $argv0 執行結果以下: [root@aliyun pratice]# expect var.exp ywxi.txt 192.168.1.7 /opt/ ywxi.txt 192.168.1.7 /opt/ #這是腳本後面的三個參數 3 #這是參數的總個數 var.exp #這是腳本的名字
五:Expect程序中的if條件語句
Expect程序中if條件語句的基本語法爲:
if {條件表達式} { 指令 } 或 if {條件表達式} { 指令 } else { 指令 } 說明:if關鍵字後面要有空格,else關鍵字先後都要有空格,{條件表達式}大括號裏面靠近大括號處能夠沒有空格,將指令括起來的起始大括號"{"前要有空格。
範例以下:使用if語句判斷腳本傳參的個數,若是不符合則給予提示。
[root@aliyun pratice]# cat ifexp.exp #!/usr/bin/expect if { $argc != 3 } { send_user "usage: expect $argv0 file host dir\n" exit } set file [lindex $argv 0] set host [lindex $argv 1] set dir [lindex $argv 2] puts "$file\t$host\t$dir" [root@aliyun pratice]# expect ifexp.exp usage: expect ifexp.exp file host dir [root@aliyun pratice]# expect ifexp.exp 1 2 3 1 2 3