zoukankan      html  css  js  c++  java
  • expect实现非交互

    一、exepct介绍

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

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

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

    二、expect程序自动交互

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

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

    例如:

           spawn ssh root@192.168.4.5 uptime

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

    expect命令语法

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

    expect    表达式    [动作]

    例如:

    spawn ssh root@192.168.4.5 uptime

    expect “*password” {send “666666 ”}

    send 发送字符串

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

     

    2.1 实现自动交互

    #!/usr/bin/expect

    spawn ssh root@192.168.4.5 uptime

    expect {

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

            "*password" {exp_send "666666 "}

    }

    expect eof

    expect_send和send类似, 回车

    expect{},类似多行expect。

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

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

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

    [root@localhost ~]# 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"

     

    [root@localhost ~]# sh xinxi.sh

    pls input your username:calabash

    pls input your password:666666

    pls input your email:calabash@163.com

    your name is calabash ,your passwordis 666666 ,your emali is calabash@163.com

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

    [root@localhost ~]# vim expxinxi.exp

    #!/usr/bin/expect

    spawn /bin/sh xinxi.sh

    expect {

            "username" {exp_send "calabash ";exp_continue}

            "password" {send "666666 ";exp_continue}

            "email" {exp_send "calabash@163.com "}

    }

    expect eof

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

    [root@localhost ~]# expect expxinxi.exp

    spawn /bin/sh xinxi.sh

    pls input your username:calabash

    pls input your password:666666

    pls input your email:calabash@163.com

    your name is calabash ,your passwordis 666666 ,your emali is calabash@163.com

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

    [root@localhost ~]# vim me.exp

    #!/usr/bin/expect

    send_user "I am calabash. "

    send_user "I am a linuxer. "

    send_user "mysql email is calabash@163.com "

     

    [root@localhost ~]# expect me.exp

    I am calabash.

    I am a linuxer.       mysql email is calabash@163.com

     

       换行

       tab键

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

    例如:

    [root@localhost ~]# vim me.exp

    #!/usr/bin/expect

    send_user "I am calabash. "

    send_user "I am a linuxer. "

    send_user "mysql email is calabash@163.com "

    exit -onexit {

            send_user "Good bye. "

    }

    [root@localhost ~]# expect me.exp

    I am calabash.

    I am a linuxer.       mysql email is calabash@163.com

    Good bye.

    2.3 常用命令总结

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

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

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

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

    send_user:打印脚本信息

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

    三、expect程序变量

    3.1普通变量

    定义变量:

    set  变量名        变量值

    打印变量:

    puts     $变量名

    示例:

    [root@localhost ~]# vim shili.exp

    #!/usr/bin/expect

    set password "666666"

    puts $password

    send_user "$password "

     

    [root@localhost ~]# 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参数]

    例如:

    [root@localhost ~]# vim shili.exp

    #!/usr/bin/expect

    set file [lindex $argv 0]

    set host [lindex $argv 1]

    set dir [lindex $argv 2]

    puts "$file $host $dir "

    puts $argc

    puts $argv0

     

    加三个位置参数

    [root@localhost ~]# 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秒后超时返回

    [root@localhost ~]# vim shili.exp

    #!/usr/bin/expect

    spawn ssh roo@192.168.4.5 uptime

    set timeout 5

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

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

     

    [root@localhost ~]# expect shili.exp

    spawn ssh roo@192.168.4.5 uptime

    roo@192.168.4.5's password: Request timeout by calabash.

     

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

    [root@localhost ~]# vim shili.exp

    #!/usr/bin/expect

    spawn ssh roo@192.168.4.5 uptime

    expect {

            -timeout 3

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

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

    }

     

    [root@localhost ~]# expect shili.exp

    spawn ssh roo@192.168.4.5 uptime

    roo@192.168.4.5's password: Request timeout by calabash.

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

    4.1 if语句的语法

           if  { 条件表达式 }  {

           指令

    }

    或者

    if  { 条件表达式 }  {

           指令

    }  else  {

           指令

    }

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

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

    4.2 if判断示例

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

    [root@localhost ~]# vim shili.exp

    #!/usr/bin/expect

    if { $argc != 26 } {

            puts "bad."

    } else {

            puts "good."

    }

     

    [root@localhost ~]# expect shili.exp

    bad.

    [root@localhost ~]# expect shili.exp {a..z}

    good.

    五、expect生产环境案例

    5.1 实现自动交互的脚本

    [root@G ~]# 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 root@$ip $cmd

    expect {

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

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

    }

    expect eof

    脚本后加上ip和命令

    [root@G ~]# expect zd.exp 192.168.4.5 uptime

    spawn ssh root@192.168.4.5 uptime

    root@192.168.4.5'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

    被管理机

    [root@G ~]# 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

     

    [root@G ~]# sh pl.sh uptime

    spawn ssh root@192.168.4.5 uptime

    root@192.168.4.5's password:

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

    spawn ssh root@192.168.4.6 uptime

    root@192.168.4.6's password:

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

    5.3 免交互发送文件

    [root@G ~]# 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 root@$host:$dir

    expect {

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

            "*password" {send "$password "}

    }

    expect eof

     

    发送文件

    [root@G ~]# expect scpfile.exp abc 192.168.4.6 /root/

    spawn scp -rp -P22 abc root@192.168.4.6:/root/

    root@192.168.4.6's password:

    查看发送结果

    [root@G ~]# expect zd.exp 192.168.4.6 ls

    spawn ssh root@192.168.4.6 ls

    root@192.168.4.6's password:

    abc

    anaconda-ks.cfg

    install.log

    install.log.syslog

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

    [root@G ~]# 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

     

    [root@G ~]# sh scpfile.sh wangluyu /root/

    spawn scp -rp -P22 wangluyu root@192.168.4.5:/root/

    root@192.168.4.5's password:

    spawn scp -rp -P22 wangluyu root@192.168.4.6:/root/

    root@192.168.4.6's password:

  • 相关阅读:
    解决UITableView中Cell重用机制导致内容出错的方法总结
    Hdu 1052 Tian Ji -- The Horse Racing
    Hdu 1009 FatMouse' Trade
    hdu 2037 今年暑假不AC
    hdu 1559 最大子矩阵
    hdu 1004 Let the Balloon Rise
    Hdu 1214 圆桌会议
    Hdu 1081 To The Max
    Hdu 2845 Beans
    Hdu 2955 Robberies 0/1背包
  • 原文地址:https://www.cnblogs.com/calabash/p/7707260.html
Copyright © 2011-2022 走看看