【shell脚本6】expect交互应答语句(自动匹配回答问题)

一、使用说明

当我们执行ssh远程连接命令时,有时让输入用户密码,有时需要输入是否——yes/no继续建立连接,如果我们想要编写一个可以自动执行远程连接操作的脚本,就需要根据shell中具体的交互信息作出不同的回答,类似这种情况在编写脚本时就需要使用expect语句

二、使用方法

(1)、创造模拟环境

编写问题脚本,运行脚本时逐个输出提示语提示用户输入姓名、年龄和学科,读取用户输入的字符串并将其赋值给相应的变量,输出显示变量值的组合语句

问题脚本

read -p "What is your name: " NAME
read -p "How old are you: " AGE
read -p "Which subject do you like : " SUBJECT
echo $NAME is a $AGE old person which like $SUBJECT

执行效果
第一种
逐个输入回答问题
在这里插入图片描述

第二种方式
提前准备好输入,准备应答
在这里插入图片描述

(2)、expect的使用

expect语句来根据shell中具体的交互信息自动作出不同的回答

dnf install expect -y

安装完成后,当我们编写问题脚本(.sh结尾),脚本中需要用户多次输入内容回答问题时,可以编写相应的应答expect脚本(以.exp结尾)自动检测其监控执行的脚本(.sh)所提示的问题,根据问题的关键字匹配对应的回答给问题脚本。except和shell一样有自己运行的环境(#!/usr/bin/expect),应答expect脚本主要有以下四种编写方式:

1)、编写方式一

在 expect 环境中使用多个单独的内部命令expect,判断交互中输出的信息里是否包含某些关键字,如果有则立即根据关键字匹配对应的回答并将回答send发送给问题脚本

注意:
1、每个回答后的 \r 必须写,否则会卡住出错;
2、spwan监控执行脚本,传递交互指令;
3、脚本结束标志可以为xcept eof、interact,except eof表示结束当前except运行环境,interact表示保留当前except运行环境并退出;

vim answer.exp
///

#!/usr/bin/expect                     运行的环境
spawn /root/question.sh               回答文件的位置
expect "name"
send "ck\r"
expect "old"
send "24\r"
expect "subject"
send "linux\r"
expect eof

执行后结果显示
自动匹配问题
在这里插入图片描述

2)、编写方式二

我们可以在一个expect模块中写入多个关键字,这样当expect脚本中回答数量多于问题脚本(.sh结尾)所提示的问题时,多出的回答不会导致匹配出错,这里exp_continue参数的功能是使同一expect模块中的匹配语句可以继续执行
注意模块内最后一个回答不用写exp_continue参数,否则会卡住出错

vim answer1.exp
///

#!/usr/bin/expect
spawn /root/question.sh
expect  {
    "name" {  send "ck\r";exp_continue }
    "color" {  send "blue\r";exp_continue }           多写了一行,进行测试。
    "old" { send "22\r";exp_continue  }
    "subject" { send "linux\r"  }
}
expect eof

多写的一行不会影响匹配机制
在这里插入图片描述

3)、编写方法三

我们可以使用变量读取执行except脚本时脚本后用户输入的字符串,将其作为问题关键字对应匹配的回答,实现了动态应答功能,这里set timeout 数字表示应答出现问题出错时最多等待几秒就结束运行/

注意定义变量稍微有点不同,且最后一个一定要是能回答的

vim answer2.exp
/
#!/usr/bin/expect
set timeout 3
set NAME [ lindex $argv 0 ]                   $argv 0表示except脚本后跟的第一个字符,以此类推
set OLD [ lindex $argv 1 ]
set SUBJECT [ lindex $argv 2 ]
set COLOR [ lindex $argv 3 ]                  多写一行
spawn /root/question.sh
expect {
  "name" { send "$NAME\r";exp_continue }
  "old" { send "$OLD\r";exp_continue }
  "color" { send "$COLOR\r";exp_continue}
  "subject" { send "$SUBJECT\r" }          
}
expect eof

分别赋予变量NAME,OLD,SUBJECT,COLOR的值为ck,24,linux,blue结果如下
在这里插入图片描述

4)、编写方法四

当应答脚本需要和shell脚本一起运行的时候,需要同一在/bin/bash进行运行。此时可以采用编写方法三、将expect的相关命令使用EOF输入到except运行环境中运行,注意此时expect模块中的内容要顶格写,此时可以使用sh xxx.exp的方式运行expect脚本

注意运行环境为/bin/bash

vim answer2.exp
///
 
#!/bin/bash
/usr/bin/expect <<EOF
spawn /root/question.sh
expect  {
"name" { send "$1\r";exp_continue }
"old" { send "$2\r";exp_continue }
"color" { send "$3\r" ;exp_continue}              多写了一行
"subject" { send "$4\r" }                         这行一定要有应答,不然会出错
}
expect eof
EOF

用普通脚本的方式进行
在这里插入图片描述

三、练习

编写脚本host_list.sh检测172.25.254.190-172.25.254.201网络是否开启,如果网络正常则生成解析列表host_list,解析列表格式为:ip 主机名称

思路:使用for循环依次ping172.25.254.190-172.25.254.201网络,如果可以ping通则将网络ip和通过远程连接执行hostname命令得到的主机名保存在解析列表文件host_list中,这里要注意,当我们需要进行远程连接时,有时系统会提示请回答连接主机的密码,有时系统会提示请回答是否进行连接,所以我们需要编写一个expect自动应答函数,监控执行远程连接命令,根据提示的问题自动匹配回答

vim jiaoben.sh
/

#!/bin/bash
Autossh()                                              这里写了一个应答函数
{
/usr/bin/expect <<EOF
spawn ssh -l root $1 $2                                在每次的for循环里面$1代表ip,$2代表询问hostanme
expect {
"yes/no" { send "yes\r;exp_continue" }
"password" { send "westos\r;exp_continue" }
}
expect eof
EOF
}

for ID in {190..201}                                   
do
  ping -c1 -w1 172.25.42.$ID &> /dev/null && {
  echo -e "172.25.42.$ID\t `Autossh 172.25.42.$ID hostname|tail -n1`" >> /root/host_list
}
done

因为我们开启了一台172.25.42.200的主机,主机名字为p2,所以只记录了这台主机的信息。
在这里插入图片描述

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值