centos7 自動交互expect 安裝使用


原文鏈接:https://blog.csdn.net/qq_41944882/article/details/105956317

一、概述
通過Shell可以實現簡單的控制流功能,如:循環、判斷等。但是對於需要交互的場合則必須通過人工來干預,有時候我們可能會需要實現和交互程序如telnet服務器等進行交互的功能。而Expect就使用來實現這種功能的工具。
Expect是一個免費的編程工具語言,用來實現自動與交互式任務進行通信,而無需人工干預。Expect是一個用來實現自動交互功能的軟件套件 。系統管理員可以用它來創建腳本以實現對命令或程序提供輸入,而這些命令和程序是期望從終端(terminal)輸入的,一般來說這些輸入都需要手工輸入。 Expect則可以根據程序的提示模擬標准輸入提供給程序需要的輸入來實現交互程序執行。甚至可以實現實現簡單的BBS聊天機器人。Expect是不斷發展的,隨着時間的流逝,其功能越來越強大,已經成為系統管理員的的一個強大助手。Expect需要Tcl編程語言的支持,要在系統上運行Expect必須首先安裝Tcl。

二、Expect工作原理
從最簡單的層次來說,Expect的工作方式象一個通用化的Chat腳本工具。Chat腳本最早用於UUCP網絡內,以用來實現計算機之間需要建立連接時進行特定的登錄會話的自動化。
Chat腳本由一系列expect-send對組成:expect等待輸出中輸出特定的字符,通常是一個提示符,然后發送特定的響應。例如下面的 Chat腳本實現等待標准輸出出現Login:字符串,然后發送somebody作為用戶名;然后等待Password:提示符,並發出響應 sillyme。
引用:login: somebody pssword: sillyme
這個腳本用來實現一個登錄過程,並用特定的用戶名和密碼實現登錄,Expect最簡單的腳本操作模式本質上和Chat腳本工作模式是一樣的。

三、安裝expect
1.yum源安裝expect,使用yum源可以自動解決依賴

[root@test1 man]# yum -y install expect

2.源碼包方式安裝expect
(1)安裝tcl軟件包,因為expect依賴於tcl,所以得先解決依賴問題
這里安裝8.4.19版本

[root@test1 mnt]# wget https://sourceforge.net/projects/tcl/files/Tcl/8.4.19/tcl8.4.19-src.tar.gz

解壓縮並安裝tcl

[root@test1 mnt]# tar -zxvf tcl8.4.19-src.tar.gz
[root@test1 mnt]# cd tcl8.4.19/unix && ./configure --prefix=/usr/tcl && make && make install

(2)下載expect並安裝
這里下載expect5.45

[root@test1 mnt]# wget http://sourceforge.net/projects/expect/files/Expect/5.45/expect5.45.tar.gz

解壓縮並安裝exxpect

[root@test1 mnt]# tar -zxvf expect5.45.tar.gz
[root@test1 mnt]# cd expect5.45/ && ./configure --prefix=/usr/expect --with-tcl=/usr/tcl/lib --with-tclinclude=../tcl8.4.19/generic && make && make install
[root@test1 expect5.45]# ln -s /usr/tcl/bin/expect /usr/bin/expect

四、expect的語法
語法:expect [選項] [ -c cmds] [ [ -[f|b] ] cmdfile] [ args]
選項:-c:從命令行執行expect腳本,默認expect是交互地執行的 -d:可以輸出輸出調試信息

expect中相關命令:

spawn:啟動新的進程
send:用於向進程發送字符串
expect:從進程接收字符串
interact:允許用戶交互
exp_continue:匹配多個字符串在執行動作后加此命令
expect:最常用的語法(tcl語言:模式-動作)
set timeout 30:設置超時時間timeout為30s,expect命令阻塞超時時會自動往下繼續執行。將timeout配置為-1時表示expect一直阻塞直到與期待的字符串匹配上才繼續往下執行。超時時間timeout默認為10s。
[lindex $argv n]:可以在腳本中使用該命令獲取在腳本執行時傳入的第n個參數。這里argv為傳入的參數,另外argv為傳入的參數,另外argc表示傳入參數的個數,$argv0表示腳本名字。另外我們也可以使用[lrange $argv sn en]命令獲取第sn到第en個參數。

實用代碼分析
通過一些常用的expect腳本來具體的說明如何使用expect來完成日常的一些工作

#!/usr/bin/expect //使用expect來解釋該腳本
set timeout 30 //設置超時時間,單位為秒,默認情況下是10秒
set host "192.168.33.124" //設置變量
set username "root"
set pass "123456"
spawn ssh $username@$host //spawn:是進入expect環境后才可以執行的expect內部命令,如果沒有裝expect或者直接在默認的SHELL下執行是找不到spawn命令的。它主要的功能是給ssh運行進程加個殼,用來傳遞交互指令
expect "*password*" {send "$pass\r"} //這里的expect也是expect的一個內部命令,這個命令的意思是判斷上次輸出結果里是否包含“password”的字符串,如果有則立即返回;否則就等待一段時間后返回,這里等待時長就是前面設置的30秒
interact //執行完成后保持交互狀態,把控制權交給控制台,這個時候就可以手工操作了。如果沒有這一句登錄完成后會退出,而不是留在遠程終端上

在上述的示例中,涉及到expect中一個非常重要的概念——模式-動作;即上述expect "*password*" {send "$password\r"}這句代碼表達出來的含義。簡單的說就是匹配到一個模式,就執行對應的動作;匹配到password字符串,就輸入密碼。你可能也會看到這樣的代碼:

expect {
"password" {
send "$pass\r"
exp_continue
}
eof
{
send "eof"
}
}

其中exp_continue表示循環式匹配,通常匹配之后都會退出語句,但如果有exp_continue則可以不斷循環匹配,輸入多條命令,簡化寫法。

很多時候,我們需要傳遞參數到腳本中,現在通過下面這段代碼來看看如何在expect中使用參數:

#!/usr/bin/expect
if {$argc < 3} {
puts "Usage:cmd <host> <username> <password>"
exit 1
}
set timeout -1
set host [lindex $argv 0]
set username [lindex $argv 1]
set pass [lindex $argv 2]
spawn ssh $username@$host
expect "*password*" {send "$pass\r"}
interact

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

五、expect應用實例
1.傳參式ssh登陸指定主機

#!/usr/bin/expect -f
set ip [ lindex $argv 0 ] //接收第一個參數,並設置IP
set pass [ lindex $argv 1 ] //接收第二個參數,並設置密碼
set timeout 10 //設置超時時間
spawn ssh root@$ip //發送ssh請求
expect { //返回信息匹配
"*yes/no" { send "yes\r"; exp_continue} //第一次ssh連接會提示yes/no,自動發送yes
"*password:" { send "$pass\r" } //出現密碼提示,發送密碼
}
interact //交互模式,用戶會停留在遠程服務器上面

2.利用expect批量ssh互信
編寫hosts文本用於存放主機信息,格式如下:

編寫腳本,如下所示:

#!/bin/bash

# 判斷id_rsa密鑰文件是否存在
if [ ! -f ~/.ssh/id_rsa ];then
ssh-keygen -t rsa -P "" -f ~/.ssh/id_rsa
else
echo "id_rsa has created ..."
fi

#分發到各個節點,這里分發到host文件中的主機中.
while read line
do
user=`echo $line | cut -d " " -f 2`
ip=`echo $line | cut -d " " -f 1`
passwd=`echo $line | cut -d " " -f 3`

expect <<EOF
set timeout 10
spawn ssh-copy-id $user@$ip
expect {
"yes/no" { send "yes\n";exp_continue }
"password" { send "$passwd\n" }
}
expect "password" { send "$passwd\n" }
EOF
done < hosts

由於是做實驗,只在hosts文件里放了一台機器的信息,如果是很多太機器的話,可以把其他機器的信息按照相同的格式放入hosts文件中,運行該腳本的機器都可以免密ssh登陸其他機器,如果需要相互之間都能免密登陸,則每台機器都執行該腳本,可以結合saltsatck自動化運維工具來使每台機器都執行該腳本。


免責聲明!

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



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