expect 基础要知道:
- expect是自动应答用于交互式的命令(相对于语句,更像是命令);
- spawn 是expect中的监控程序,运行后会监控命令提出的交互问题;
- send 发送问题答案给交互命令
- exp_continue 表示当问题答案不存在时继续回答下面的问题;
- expect eof 表示问题回答完毕退出expect环境
- interact 表示问题回答完毕依旧停留在交互界面(一般用于远程登陆时)
- set NAME(变量名)[ lindex $argv n ] 定义变量
yum install -y expect.x86_64 ##安装expect软件才能使用expect
expect 脚本一般以#!/usr/bin/expect 开头,规定脚本的运行环境(expect的运行环境不同与shell脚本的运行环境)
spawn 新建一个进程,这个进程的交互由expect控制
示例:
存在一个交互式脚本(shell脚本)
[root@localhost ~]# cat ask.sh
####################################
#Author: Linux #
#Version: 7.3 #
#Mail: Linux@toto.com #
#Create_Date: 2019-08-23 02:24:36 #
#Description: #
# #
####################################
#!/bin/bash
read -p "what's your name: " NAME
read -p "where are you from: " ADDR
read -p "how old are you: " AGE
read -p "what are you doing: " ACTION
echo "$NAME come from $ADDR ,now $AGE years old,is $ACTION"
[root@localhost ~]# sh ask.sh ##执行该脚本时需要 一步步输入所要的参数
what's your name: lily
where are you from: shannxi
how old are you: 24
what are you doing: learning linux
lily come from shannxi ,now 24 years old,is learning linux
使用expect可以一次自动回答所有问题(注意:被检控的文件必须要有执行权限)
[root@localhost ~]# chmod +x /mnt/ask.sh
[root@localhost mnt]# cat answer.exp
#!/usr/bin/expect
set NAME [ lindex $argv 0 ]
set ADDR [ lindex $argv 1 ]
set AGE [ lindex $argv 2 ]
set ACTION [ lindex $argv 3 ]
spawn /mnt/ask.sh
expect {
"name" { send "$NAME\r";exp_continue }
"from" { send "$ADDR\r";exp_continue }
"old" { send "$AGE\r";exp_continue }
"doing" { send "$ACTION\r" }
}
expect eof
[root@localhost mnt]# expect answer.exp lily China 18 linux
spawn /mnt/ask.sh
what's your name: lily
where are you from: China
how old are you: 18
what are you doing: linux
lily come from China ,now 18 years old,is linux
expect应用示例:
ssh 远程连接主机,并显示主机名
[root@localhost mnt]# cat ip.exp
#!/usr/bin/expect
set timeout 5
set IP [ lindex $argv 0 ]
set PASSWORD [ lindex $argv 1 ]
spawn ssh root@$IP hostname
expect {
"yes/no" {send "yes\r";exp_continue}
"password" {send "$PASSWORD\r";}
}
interact
[root@localhost mnt]# expect ip.exp 172.25.254.23 westos
spawn ssh root@172.25.254.23 hostname
root@172.25.254.23's password:
foundation
操作中需要两种不同的环境,很不方便
那么我们也可以将expect环境修改成在shell脚本中运行的环境
[root@localhost mnt]# cat check_ip.sh
####################################
#Author: Linux #
#Version: 7.3 #
#Mail: Linux@toto.com #
#Create_Date: 2019-08-23 03:25:55 #
#Description: #
# #
####################################
#!/bin/bash
Auto_Connect()
{
/usr/bin/expect <<EOF
spawn ssh root@$1 $2
expect {
"yes/no" { send "yes\r";exp_continue }
"password" {send "westos\r"}
}
expect eof
EOF
}
Auto_Connect $1 hostname
[root@localhost mnt]# sh check_ip.sh 172.25.254.23 westos
spawn ssh root@172.25.254.23 hostname
root@172.25.254.23's password:
foundation
批量自动ping可以连接的主机获取主机名 ip ,把内容指定放入hostfile文件
[root@localhost mnt]# cat check_ip.sh
####################################
#Author: Linux #
#Version: 7.3 #
#Mail: Linux@toto.com #
#Create_Date: 2019-08-23 03:25:55 #
#Description: #
# #
####################################
#!/bin/bash
Auto_Connect()
{
/usr/bin/expect <<EOF
spawn ssh root@$1 $2
expect {
"yes/no" { send "yes\r";exp_continue }
"password" {send "westos\r"}
}
expect eof
EOF
}
for NUM in {1..10}
do
ping -c1 -w1 172.25.254.$NUM &> /dev/null
if [ "$?" = "0" ]
then
echo "`Auto_Connect 172.25.254.$NUM hostname | tail -n 1` A 172.25.254.$NUM" >>/mnt/host_list
fi
done
[root@localhost mnt]# sh check_ip.sh
执行完脚本会出现上图的情况,多出^M实际是换行符
注意:
ctrl + v 和crtl +m —>^M (shell脚本出现)
不同的操作系统换行符也不同:
windows系统:/r/n换行;
linux系统:/r换行;
unix系统:/n换行;(一般沿用的方法)
优化脚本:
#!/bin/bash
Auto_Connect()
{
/usr/bin/expect <<EOF
spawn ssh root@$1 $2
expect {
"yes/no" { send "yes\r";exp_continue }
"password" {send "westos\r"}
}
expect eof
EOF
}
for NUM in {1..10}
do
ping -c1 -w1 172.25.254.$NUM &> /dev/null
if [ "$?" = "0" ]
then
echo "`Auto_Connect 172.25.254.$NUM hostname | tail -n 1` A 172.25.254.$NUM" >>/mnt/host_list
fi
sed 's/^M//g' /mnt/host_list -i
done
###shell的基本运算符号####
运算符号 | 意义 |
---|---|
+,- | 加法,减法 |
*,/,% | 乘法,除法,取余 |
** | 幂运算 |
<,<=,>,>= | 比较符号 |
=,+=,-=,*=,/=,%= | 赋值运算 例如.a+=1,相当于a=a+1 |
示例应用:
用计算的方法写一个一分十秒的倒计时脚本;
#!/bin/bash
read -p "please input the min: " MIN
read -p "please input the sec: " SEC
#将所有的时间转换成秒数
MAX_Sec=$[60*$MIN+$SEC]
for ((;MAX_Sec>0;MAX_SEC--)) ##设定循环条件
do
Min=$[$MAX_SEC/60]
Sec=$[$MAX_SEC%60]
echo -ne "After $Min : $Sec is end "
echo -ne "\r"
sleep 1
done