linux expect自动交互命令

linux expect自动交互命令

工作中遇到批量服务器无交互情况,但又不能使用秘钥免密,尴尬了。百度了一下无交互命令expect,做个笔记分享。

安装

yum方式安装
yum -y insatll
tar包方式安装

expect安装需要tcl依赖。

tcl源码包:https://sourceforge.net/projects/tcl/files/latest/download

expect源码包:https://sourceforge.net/projects/expect/files/latest/download

日常应用expect为两种方法:

  • 1.独立expect脚本应用
  • 2.shell嵌套expect命令

第一种应用:独立expect脚本

制作独立的expect脚本,一般以exp作为后缀名。

 1)定义脚本执行的shell:
 #!/usr/bin/expect
 2)set timeout(expect的内部命令)
 设置超时时间,单位是秒,值为-1时 永不超时(当远端命令执行时间较长时,需要注意此参数,譬如日志分割操作,会占用较长时间,可用到此参数)。
 如30秒:timeout 30 
 3)spawn (expect的内部命令)
 功能:传递交互指令
 4)expect(expect的内部同名命令)
 主要功能:判断输出是否包含某项字符,没有立即返回(如果设置有timeout值,则等待timeout时间)
 5)send(expect的内部命令)
 功能:执行交互动作(就是远端要执行的命令!)
 命令字符串后面加“r”,表示换行,就如同我们敲完命令会有回车操作
 6)interact(expect的内部命令)
 执行完毕后保持交互状态,把控制权交给当前控制台。
 如果不加这一项,交互完成退出。
 7)exp_continue (expect的内部命令)
 继续接下来的交互操作
 8)$argv (expect的内部命令)
 expect脚本接受从bash传递过滤的参数
 格式:[ llindex $argv n ] ,n从0开始,表示第一、二、三。。。个参数 

注:以上参数中expect(内置命令)

如果以{}方式交互,可以理解为组,但只打印第一个send结果

如果想实现每个expect交互命令都有打印结果需要expect独立send命令

范例一:实现获取远端主机名、日期等,然后返回源主机

创建 ssh1.exp,关注以下几点,

1.使用set配置固定值(密码明文,不够安全)

2.expect判断字符“]*”,中*是通配符

3.send命令中“\r”,r代表回车,换行。

4.$默认引用的当前脚本变量,如果牵涉远程命令需要\$转义!

#!/usr/bin/expect
#定义变量
set IPADD "192.168.68.150"
set USER "root"
set PWD "123456789"
set timeout -1
#spawn传递交互命令
spawn ssh $USER@$IPADD
#
expect {
"yes/no" { send "yes\r"  }
"password:" { send "$PWD\r" }
}

#expect判断包含"]*"就触发send交互动作,*为通配符!
#获取远端主机名
expect "]*" {send "hostname\r"}
#获取远端主机IP($1中$需要转义,否则会被认为是变量!!!)
expect "]*" {send "hostname -I|awk '{print \$1}'\r"}
#获取远端主机时间
expect "]*" {send "date +%F_%T\r"}

#退出远端主机
expect "]*" { send "exit\r" }

测试结果:

https://qnimg.ffing.cn/wp-content/uploads/2022/01/image-35.png?imageView2/0/q/75|watermark/1/image/aHR0cHM6Ly9xbmltZy5mZmluZy5jbi9mbl9sb2dvLnBuZw==/dissolve/55/gravity/SouthEast/dx/0/dy/0

范例二:与范例一获取信息一样,不同点在于变量值在控制台输入!

使用$avgr调用追加变量

#!/usr/bin/expect
set IPADD [ lindex $argv 0 ]
set USER [ lindex $argv 1 ]
set PWD [ lindex $argv 2 ]
set timeout 30
spawn ssh $USER@$IPADD
expect {
"yes/no" { send "yes\r"  }
"password:" { send "$PWD\r" }
}
#保持交互,留着当前控制台
interact

测试结果:

https://qnimg.ffing.cn/wp-content/uploads/2022/01/image-36.png?imageView2/0/q/75|watermark/1/image/aHR0cHM6Ly9xbmltZy5mZmluZy5jbi9mbl9sb2dvLnBuZw==/dissolve/55/gravity/SouthEast/dx/0/dy/0

第二种应用:shell脚本中使用expect

在shell脚本中,expect使用EOF执行

如下脚本:用于服务器批量spc文件到远端家目录

(如暴露主机信息,可使用gpg进行脚本加密,或者将主机信息移到单独文件进行gpg,我这里只是为了演示写在一个脚本里了)

#!/bin/bash
#实现批量服务器scp传输文件到远端家目录
#只需更新SCPFILE文件路径及主机信息

#要传送的文件
SCPFILE=~/check.sh

#主机信息
echo "
#IPADD              USER                PWD
192.168.68.100      root                123456789
192.168.68.150      root                123456789

"| grep -Ev "^#|^$" >/tmp/host.txt
########################################################

SUM=`cat /tmp/host.txt |wc -l`
for i in `seq $SUM`
do

IPADD=`sed -n "$i"p /tmp/host.txt|awk '{print $1}'`
USER=`sed -n "$i"p /tmp/host.txt |awk '{print $2}'`
PWD=`sed -n "$i"p /tmp/host.txt  |awk '{print $3}'`


#scp传送巡检脚本
expect <<EOF
         set timeout -1;
         spawn  scp $SCPFILE  $USER@$IPADD:
         expect {
                 "yes/no" { send "yes\n" ; exp_continue }
                 "password:" { send "$PWD\n" }
         }
         expect eof
EOF
echo "=========$IPADD SCP完成 ================="
done
rm -f /tmp/host*

https://qnimg.ffing.cn/wp-content/uploads/2022/01/image-37.png?imageView2/0/q/75|watermark/1/image/aHR0cHM6Ly9xbmltZy5mZmluZy5jbi9mbl9sb2dvLnBuZw==/dissolve/55/gravity/SouthEast/dx/0/dy/0

——————————————————————————–

在shell脚本中,使用expect -c ” “

使用-c双引号代替EOF,但因为是双引号做标识符,使在引号内的特殊符号都需要使用\反斜杠对特殊符号进行转义,不是很方便,不喜欢。。。

#!/bin/bash
echo start

expect -c "
spawn ssh root@$192.168.68.100
expect \"password:\" { send \"123456789\r\"   }
interact
"
good good study, day day up!

发表评论

textsms
account_circle
email

linux expect自动交互命令
工作中遇到批量服务器无交互情况,但又不能使用秘钥免密,尴尬了。百度了一下无交互命令expect,做个笔记分享。 安装 yum方式安装 yum -y insatll tar包方式安装 expect安…
扫描二维码继续阅读
2022-01-31