expect实现非交互

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了expect实现非交互相关的知识,希望对你有一定的参考价值。

一、exepct介绍

expect命令是一个实现交互功能的软件套件,是基于TCL的脚本编程语言,在企业运维中,系统会以交互的形式要求运维人员输入指定的字符串,之后才能继续执行命令。例如:为用户设置密码时,一般情况下需要手工输入两次密码,比如使用ssh连接远程服务器时,第一次连和系统实现两次交互。

简单的说,expect用来自动实现与交互程序通信的,无需管理员手工干预

spawn启动指定进程>expect获取期待的关键字>send向指定进程发送字符>进程执行完毕,退出

 

二、expect程序自动交互

expect程序中的命令是expect的核心

spawn  [选项]  [需要交互的命令或程序]

例如:

       spawn ssh [email protected] uptime

在spawn命令的后面,直接要加上要执行的命令或程序

 

expect命令语法

在expect自动交互的执行过程中,当使用spawn命令执行一个命令或程序之后,会提示某些交互信息,expect命令的作用就是获取spawn命令执行的信息,看看是否有事先指定的相匹配,一旦匹配上指定的内容就执行expect后面的动作。

expect    表达式    [动作]

例如:

spawn ssh [email protected] uptime

expect “*password” {send “666666\r”}

send 发送字符串

 

当然,他也可以在一个expect匹配中多次匹配不同的字符串,并给出不同的处理动作,此时,只需要将匹配的所有字符串放在一个{}大括号中就可以了,好需要借助exp_continue指令实现继续匹配。

 

2.1 实现自动交互

#!/usr/bin/expect

spawn ssh [email protected] uptime

expect {

        "yes/no" {exp_send "yes\r";exp_continue}

        "*password" {exp_send "666666\r"}

}

expect eof

 

expect_send和send类似,\r 回车

expect{},类似多行expect。

exp_continue 匹配多个字符串,需要在每次匹配并执行动作后继续匹配,加上exp_continue

exp_eof 想要输出结果,必须加eof,表示expect结束

 

2.2利用expect响应shell脚本中的多个read读入

[[email protected] ~]# vim xinxi.sh

#!/bin/bash

read -p "pls input your username:" name

read -p "pls input your password:" pass

read -p "pls input your email:" mail

echo -n "your name is $name ,"

echo -n "your passwordis $pass ,"

echo "your emali is $mail"

 

[[email protected] ~]# sh xinxi.sh

pls input your username:calabash

pls input your password:666666

pls input your email:[email protected]

your name is calabash ,your passwordis 666666 ,your emali is [email protected]

用expect自动化脚本,实现自动输入多个字符串

[[email protected] ~]# vim expxinxi.exp

#!/usr/bin/expect

spawn /bin/sh xinxi.sh

expect {

 

        "username" {exp_send "calabash\r";exp_continue}

        "password" {send "666666\r";exp_continue}

        "email" {exp_send "[email protected]\r"}

}

expect eof

执行,全部自动输入,实现了自动化

[[email protected] ~]# expect expxinxi.exp

spawn /bin/sh xinxi.sh

pls input your username:calabash

pls input your password:666666

pls input your email:[email protected]

your name is calabash ,your passwordis 666666 ,your emali is [email protected]

 

send_user 可以用来打印expect脚本的信息,类似shell里的echo命令

[[email protected] ~]# vim me.exp

#!/usr/bin/expect

send_user "I am calabash. \n"

send_user "I am a linuxer. \t"

send_user "mysql email is [email protected]\n"

 

[[email protected] ~]# expect me.exp

I am calabash.

I am a linuxer.       mysql email is [email protected]

 

\n   换行

\t   tab键

 

exit命令类似于shell脚本的exit,即直接退出expect脚本,除了最基本的退出,还可以利用exit做一些提示

例如:

[[email protected] ~]# vim me.exp

#!/usr/bin/expect

send_user "I am calabash. \n"

send_user "I am a linuxer. \t"

send_user "mysql email is [email protected]\n"

exit -onexit {

        send_user "Good bye.\n"

}

[[email protected] ~]# expect me.exp

I am calabash.

I am a linuxer.       mysql email is [email protected]

Good bye.

 

2.3 常用命令总结

spawn:用过spawn执行一个程序或命令,之后所有的expect操作都在这个执行的程序或命令中执行。

expect:获取spawn程序的交互信息,查看是否和其事先指定的信息想匹配。

send:当expect匹配了指定的字符串后,发送指定的字符串给系统,这些命令可以支持一些特殊的转义符号,例如: \r回车 \n换行       \t  tab等

exp_contine:继续匹配expect程序或命令

send_user:打印脚本信息

exit:退出expect脚本,也可以做清理或提示工作

 

三、expect程序变量

3.1普通变量

定义变量:

set  变量名        变量值

 

打印变量:

puts     $变量名

示例:

[[email protected] ~]# vim shili.exp

#!/usr/bin/expect

set password "666666"

puts $password

send_user "$password\n"

 

[[email protected] ~]# expect shili.exp

666666

666666

 

3.2 特殊参数变量

在expect里也有与shell脚本里的$0 $1 $2 等类似的特殊参数变量,用于接收控制expect脚本传参

在expect中$argv表示参数数组,可以使用[lindex $argv n]接收expet脚本传参,n从0开始,分别表示第一个[lindex $argv 0]参数、第二个[lindex $argv 1]、第三个[lindex $argv 2参数]

例如:

[[email protected] ~]# vim shili.exp

#!/usr/bin/expect

set file [lindex $argv 0]

set host [lindex $argv 1]

set dir [lindex $argv 2]

puts "$file\t $host\t $dir\n"

puts $argc

puts $argv0

 

加三个位置参数

[[email protected] ~]# expect shili.exp a.txt 192.168.4.5 /root

a.txt     192.168.4.5   /root

 

3

shili.exp

$argc  表示传参的个数

$argv0  表示脚本本身的名字

 

3.3 关键字变量

timeout是一个控制时间的关键字变量,是一个全局性时间的控制开关,可以通过为这个变量赋值来规定整个expect操作的时间。因为作用于全局,即使命令没有错误,到了时间仍然会激活这个变量,此外,到时间后还会激活一个处理及提示信息开关。

示例:

此脚本测试超时返回值,所以不设置密码,5秒后超时返回

 

[[email protected] ~]# vim shili.exp

#!/usr/bin/expect

spawn ssh [email protected] uptime

set timeout 5

expect "yes/no" {exp_send "yes\r;exp_continue"}

expect timeout {puts "Request timeout by calabash.";return}

 

[[email protected] ~]# expect shili.exp

spawn ssh [email protected] uptime

[email protected]‘s password: Request timeout by calabash.

 

 

此外,在expect{}用法,还可以这样使用timeout

[[email protected] ~]# vim shili.exp

#!/usr/bin/expect

spawn ssh [email protected] uptime

expect {

        -timeout 3

        "yes/no" {exp_send "yes\r";exp_continue}

        timeout {puts "Request timeout by calabash.";return}

}

 

[[email protected] ~]# expect shili.exp

spawn ssh [email protected] uptime

[email protected]‘s password: Request timeout by calabash.

四、expect程序中的if条件语句

4.1 if语句的语法

       if  { 条件表达式 }  {

       指令

}

或者

if  { 条件表达式 }  {

       指令

}  else  {

       指令

}

 

注意:if关键字后面要有空格,else关键字前后要有空格

{条件表达式}  大括号里可以没有空格, 外面前后要有空格

 

4.2 if判断示例

 使用if语句判断脚本传参的个数,不管是否符合都给予提示

[[email protected] ~]# vim shili.exp

#!/usr/bin/expect

if { $argc != 26 } {

        puts "bad."

} else {

        puts "good."

}

 

[[email protected] ~]# expect shili.exp

bad.

[[email protected] ~]# expect shili.exp {a..z}

good.

 

五、expect生产环境案例

5.1 实现自动交互的脚本

[[email protected] ~]# vim zd.exp

#!/usr/bin/expect

if { $argc != 2 } {

        puts "usage: expect $argv0 ip command"

exit

}

#

set ip [lindex $argv 0]

set cmd [lindex $argv 1]

set password "666666"

#

spawn ssh [email protected]$ip $cmd

expect {

        "yes/no" {send "yes\r";exp_continue} &> /dev/null

        "*password" {send "$password\r"} &> /dev/null

}

expect eof

脚本后加上ip和命令

[[email protected] ~]# expect zd.exp 192.168.4.5 uptime

spawn ssh [email protected] uptime

[email protected]‘s password:

 05:15:09 up 15 min,  2 users,  load average: 0.00, 0.00, 0.00

 

5.2 利用for循环查看多台

现有2台服务器,需要用管理机去查看

Ip地址

主机名

角色

192.168.4.4

G

管理机

192.168.4.5

b1

被管理机

192.168.4.6

b2

被管理机

 

[[email protected] ~]# vim pl.sh

#!/bin/bash

if [ $# -ne 1 ];then

        echo $"USAGE:$0 cmd"

        exit 1

fi

cmd=$1

for n in 5 6

do

        expect zd.exp 192.168.4.$n "$cmd"

done

 

[[email protected] ~]# sh pl.sh uptime

spawn ssh [email protected] uptime

[email protected]‘s password:

 01:00:21 up 36 min,  2 users,  load average: 0.00, 0.00, 0.00

spawn ssh [email protected] uptime

[email protected]‘s password:

 01:00:21 up 35 min,  2 users,  load average: 0.00, 0.00, 0.00

 

5.3 免交互发送文件

[[email protected] ~]# vim scpfile.exp

#!/usr/bin/expect

if { $argc != 3 } {

        puts "usage: expect $argv0 file host dir"

        exit

}

#

set file [lindex $argv 0]

set host [lindex $argv 1]

set dir [lindex $argv 2]

set password "666666"

spawn scp -rp -P22 $file [email protected]$host:$dir

expect {

        "yes/no" {send "yes/r";exp_continue}

        "*password" {send "$password\r"}

}

expect eof

 

发送文件

[[email protected] ~]# expect scpfile.exp abc 192.168.4.6 /root/

spawn scp -rp -P22 abc [email protected]:/root/

[email protected]‘s password:

查看发送结果

[[email protected] ~]# expect zd.exp 192.168.4.6 ls

spawn ssh [email protected] ls

[email protected]‘s password:

abc

anaconda-ks.cfg

install.log

install.log.syslog

 

5.4 利用shell循环批量发送文件

[[email protected] ~]# vim scpfile.sh

#!/bin/bash

if [ $# -ne 2 ];then

        echo $"USAGE:$0 file dir"

        exit 1

fi

#

file=$1

dir=$2

for n in 5 6

do

        expect scpfile.exp $file 192.168.4.$n $dir

done

 

[[email protected] ~]# sh scpfile.sh wangluyu /root/

spawn scp -rp -P22 wangluyu [email protected]:/root/

[email protected]‘s password:

spawn scp -rp -P22 wangluyu [email protected]:/root/

[email protected]2.168.4.6‘s password:

以上是关于expect实现非交互的主要内容,如果未能解决你的问题,请参考以下文章

Expect实现ssh非交互登录

expect知识梳理

(转)SSH批量分发管理&非交互式expect

利用expect来实现非交互式备份现网网络设备配置

expect一键实现集群ssh免密登入

expect 实现自动交互脚本