• 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:

  • 相关阅读:
    MySQL 5.6.9 RC 发布
    红薯 Java 8 的日期时间新用法
    Couchbase Server 2.0 发布,NoSQL 数据库
    Firefox OS 模拟器 1.0 发布
    Calculate Linux 13 Beta 1 发布
    敏捷测试的团队构成
    Node.js 0.8.16 发布(稳定版)
    JASocket 1.1.0 发布
    Samba 4.0 正式版发布,支持活动目录
    Seafile 1.3 发布,文件同步和协作平台
  • 原文地址:https://www.cnblogs.com/calabash/p/7707260.html
Copyright © 2020-2023  润新知