Shell筆記10——Expect自動化交互式程序應用實踐

本文主要講解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
相關文章
相關標籤/搜索