一、概述
1.1 命令簡介
expect 是由Don Libes基於Tcl(Tool Command Language )語言開發的,是一種指令碼語言,主要應用於自動化互動式操作的場景,藉助Expect處理互動的命令,可以將互動過程如:ssh登入,ftp登入等寫在一個指令碼上,使之自動化完成。尤其適用於需要對多臺伺服器執行相同操作的環境中,可以大大提高系統管理人員的工作效率。
1.2 使用場景
(1)根據預定標準回答其問題,回答“是”、“否”或將控制權交還給您
(2)遠端連線裝置並執行自動化操作
(3)需要人機互動的地方,如果提前知道應該輸入什麼指令都可以使用expect 工具
1.3 expect命令安裝
yum install expect -y
二、expect使用原理
2.1 命令原理介紹
spawn啟動指定程序—expect獲取指定關鍵字—send向指定程式傳送指定字元—執行完成退出
spawn命令
spawm命令就是用來啟動新的程序的。spawn後的send和expect命令都是和spawn開啟的程序進行互動的、
send命令
send命令接收一個字串引數,並將該引數傳送到程序,這個過程類似模擬人類輸入密碼
interact命令
結合spawn、expect、send自動化的完成很多工,interact命令可以在適當的時候進行任務的干預,比如下載完ftp檔案時,仍然可以停留在ftp命令列狀態,以便手動的執行後續命令
三、expect使用語法
3.1 expect 啟用選項
-c 執行指令碼前先執行的命令,可多次使用
-d debug模式,可以在執行時輸出一些診斷資訊,與在指令碼開始處使用exp_internal 1相似。
-D 啟用交換調式器,可設一整數引數。
-f 從檔案讀取命令,僅用於使用#!時。如果檔名為"-",則從stdin讀取(使用"./-"從檔名為-的檔案讀取)。
-i 互動式輸入命令,使用"exit"或"EOF"退出輸入狀態
-- 標示選項結束(如果你需要傳遞與expect選項相似的引數給指令碼時),可放到#!行:#!/usr/bin/expect --
-v 顯示expect版本資訊
3.2 expect命令引數
spawn: 互動程式開始,執行後面的命令或程式。需要進入到expect環境才可以執行,不能直接在shell環境下直接執行
set timeout n : 設定超時時間,表示該指令碼程式碼需在n秒鐘內完成,如果超過,則退出。用來防止ssh遠端主機網路不可達時卡住及在遠端主機執行命令宕住。如果設定為-1表示不會超時
set: 定義變數
$argv expect指令碼可以接受bash的外部傳參,可以使用[ lindex $argv n ]n為0表示第一個傳參,為1表示第二個傳參,以此類推
expect 從互動程式程序中指定接收資訊, 如果匹配成功, 就執行send的指令互動;否則等待timeout秒後自動退出expect語句
send 如果匹配到expect接受到的資訊,就將send中的指令互動傳遞,執行互動動作。結尾處加上\r表示如果出現異常等待的狀態可以進行核查
exp_continue 表示迴圈式匹配,通常匹配之後都會退出語句,但如果有exp_continue則可以不斷迴圈匹配,輸入多條命令,簡化寫法。
exit 退出expect指令碼
expect eof: spawn程序結束後會向expect傳送eof,接收到eof代表該程序結束
interact 執行完程式碼後保持互動狀態,將控制權交給使用者。沒有該命令執行完後自動退出而不是留在遠端終端上
puts 輸出變數
四、實戰案例
4.1 登入遠端伺服器並在遠端伺服器上執行命令
#!/usr/bin/expect spawn ssh root@192.168.2.161 df -h expect "*password:" send "winner@001\n" expect eof
執行結果如下圖:
4.2 本機免密實現
#! /bin/bash # # Author: kangll # CreateTime: 2023-11-10 # Desc: 基礎環境配置,包括伺服器設定,JDK,免密,kerberos配置 # 可擴充套件到批次操作 # #set -x BASEDIR=$(cd "$(dirname "$0")"; pwd) # 載入配置 source $BASEDIR/config/global.sh ssh_networkname=(windp-aio) ssh_passwd=winner@#2023 ######################## # 生成本地ssh公鑰 ######################## create_ssh_pub(){ echo "生成本地ssh公鑰" /usr/bin/expect << eof # 設定捕獲字串後,期待回覆的超時時間 set timeout 30 # 執行命令開啟一個新的程序 spawn ssh-keygen -t rsa -b 1024 ## 開始進連續捕獲 expect { ".ssh/id_rsa)" { send "\n"; exp_continue } "Overwrite (y/n)?" { send "y\n"; exp_continue } "no passphrase):" { send "\n"; exp_continue } "passphrase again:" { send "\n"; exp_continue } } eof } ######################## # 定義複製ssh公鑰方法 ######################## copy_ssh(){ if [ ! -f /root/.ssh/id_rsa.pub ];then create_ssh_pub fi echo "複製公鑰到對應的主機上" /usr/bin/expect << eof # 設定捕獲字串後,期待回覆的超時時間 set timeout 30 # 命令執行 spawn ssh-copy-id -i /root/.ssh/id_rsa.pub $1@$2 ## 開始進連續捕獲 expect { "connecting (yes/no)?" { send "yes\n"; exp_continue } "s password:" { send "${ssh_passwd}\n"; exp_continue } } eof } ######################## # 配置免密 ######################## config_ssh() { # 主機遍歷 for name in ${ssh_networkname[*]};do timeout 5 ssh root@${name} "echo ${name}: 'This is success!'" if [[ $? -ne 0 ]];then echo "複製檔案到: ${name}" copy_ssh root ${name} > /dev/null fi done echo "********** ssh installation completed **********" } # 配置root使用者免密 config_ssh
4.3 自動生成kerberos使用者的keytab認證檔案
#! /bin/bash # # Author: kangll # CreateTime: 2023-11-10 # Desc: 基礎環境配置,包括伺服器設定,JDK,免密,kerberos配置 # 可擴充套件到批次操作 # # public 主機名和root密碼 ip=$(ip addr show | grep -E 'inet [0-9]' | awk '{print $2}' | awk -F '/' '{print $1}' | sed -n '$p') ssh_hosts=${ip} ssh_networkname=(windp-aio) # global.sh 配置檔案中獲取 ssh_passwd=$root_passwd ssh_passwd=winner@#2023 kerberos_user=winner_spark ################################## # 配置kerberos使用者: winner_spark # 生成keytab 檔案 ################################## config_kerberos_user() { echo "******** 建立winner_spark使用者例項 ********" /usr/bin/expect << eof # 設定捕獲字串後,期待回覆的超時時間 set timeout 30 # 登入 spawn kadmin.local ## 開始進連續捕獲,新增使用者 expect { "kadmin.local:" { send "addprinc ${kerberos_user}\n"; exp_continue } "Enter password for principal" { send "${ssh_passwd}\n"; exp_continue } "Re-enter password for principal" { send "${ssh_passwd}\n"; } } expect "kadmin.local:" { send "quit\r"; } eof echo "******** winner_spark使用者生成keytab檔案 ********" /usr/bin/expect << eof # 設定捕獲字串後,期待回覆的超時時間 set timeout 30 spawn kadmin.local ## 開始進連續捕獲,生成keytab file expect { "kadmin.local:" { send "xst -k /etc/security/keytabs/${kerberos_user}.keytab ${kerberos_user}@WINNER.COM\n"; } } expect "kadmin.local:" { send "quit\r"; } eof # modify keytab file privilege chown ${kerberos_user}:hadoop /etc/security/keytabs/${kerberos_user}.keytab echo "********** kerberos user winner_spark add completed **********" } # 配置kerberos,並啟動 #config_krb5 # 配置kerberos使用者: winner_spark, 生成keytab 檔案 config_kerberos_user