zoukankan      html  css  js  c++  java
  • expect实现自动交互由浅入深

    expect实现自动交互由浅入深

    作为运维人员可以通过Shell可以实现简单的控制流功能,如:循环、判断等。但是对于需要交互的场合则必须通过人工来干预,有时候我们可能会需要实现和交互程序如telnet服务器等进行交互的功能。而Expect就使用来实现这种功能的工具。Expect是一个免费的编程工具语言,用来实现自动和交互式任务进行通信,而无需人的干预。

    安装expect,直接yum install expect -y

    expect中相关命令

    命令 解释
    spawn 启动新的进程
    send 用于向进程发送字符串
    expect 从进程接收字符串
    interact 允许用户交互
    exp_continue 匹配多个字符串在执行动作后加此命令

    一般步骤:

    启动expect进程(spawn)--> 接收进程字符串(expect) --> 匹配字符串,成功发送字符串(send),否则等待 --> 结束

    好了就直接步入主题吧,不扯那些没用的。直接上实例:

    一. 入门例子:实现自动登录

    [root@localhost shell.sh]# vim test.exp
    #!/usr/bin/expect
    set timeout 30
    spawn ssh -l root 192.168.1.106
    expect {
    "(yes/no)?" { send "yes
    " }
    "password:" { send "jiajie
    " }
    }
    interact
    
    参数 解释
    #!/usr/bin/expect 说明使用的shell环境
    set timeout 30 设置超时时间,单位为秒,-1为没有限制
    spawn ssh... 需要执行的命令,这里是ssh登陆命令
    expect "(yes/no)?" 判断上次输出结果里是否包含(yes/no)?的字符串
    send "yes " 执行交互动作,接轨上一个命令,如果上面的expect执行成功,则发送yes
    interact 执行完成后保持交互状态,把控制权交给控制台

    执行该实例:./test.exp

    如果报错-bash: ./test.exp: Permission denied,给744权限即可。

    二. 使用变量:

    [root@localhost shell.sh]# vim test.exp

    #!/usr/bin/expect
    set ip 192.168.1.106
    set user root
    set password jiajie
    set timeout 30
    spawn ssh -l $user $ip
    expect {
    "(yes/no)?" { send "yes
    ";exp_continue }
    "password:" { send "$password
    " }
    }
    interact
    

    set:设置变量,后面直接变量,通过“$变量名”来调用

    三. 使用位置参数:

    [root@localhost shell.sh]# vim test.exp 
    
    #!/usr/bin/expect
    if {$argc!=3} {
            send_user "Usage:expect need three arguments:ip user password
    "
            exit 1
    }
    set ip [lindex $argv 0]
    set user [lindex $argv 1]
    set password [lindex $argv 2]
    set timeout 30
    spawn ssh -l $user $ip
    expect {
    "(yes/no)?" { send "yes
    ";exp_continue }
    "password:" { send "$password
    " }
    }
    interact
    

    [lindex $argv num]:表示位置参数,从num=0开始

    send_user: 打印当前提示,相当于shell里的echo.

    四. 执行多个命令:

    [root@localhost shell.sh]# vim test.exp 
    
    #!/usr/bin/expect
    if {$argc!=3} {
            send_user "Usage:expect need three arguments:ip user password
    "
            exit 1
    }
    set ip [lindex $argv 0]
    set user [lindex $argv 1]
    set password [lindex $argv 2]
    set timeout 30
    spawn ssh -l $user $ip
    expect {
    "(yes/no)?" { send "yes
    ";exp_continue }
    "password:" { send "$password
    " }
    }
    expect "]#" { send "useradd jj
    " }
    expect "]#" { send "echo jiajie|passwd --stdin jj
    " }
    send "exit
    "
    expect eof
    exit -onexit {
            send_user "useradd jj is successfully.
    "
            send_user "Jobs has finished,Goodbye.
    "
    }
    

    执行后的结果输出:

    [root@localhost shell.sh]# ./test.exp 192.168.1.106 root jiajie
    spawn ssh -l root 192.168.1.106
    root@192.168.1.106's password: 
    Last login: Sat Sep  9 03:47:48 2017 from web
    [root@localhost ~]# useradd jj
    [root@localhost ~]# echo jiajie|passwd --stdin jj
    Changing password for user jj.
    passwd: all authentication tokens updated successfully.
    [root@localhost ~]# exit
    logout
    Connection to 192.168.1.106 closed.
    useradd jj is successfully.
    Jobs has finished,Goodbye.
    

    send "exit ":登录出当前环境。

    expect eof:结束expect匹配。

    exit -onexit{...}:打印结束的提示信息。

    五. shell脚本调用expect(1)

    [root@localhost shell.sh]# vim test.sh
    
    #!/bin/bash
    ip=$1
    user=$2
    password=$3
    expect <<EOF
    set timeout 10
    spawn ssh -l $user $ip
    expect {
    "yes/no" { send "yes
    ";exp_continue }
    "password" { send "$password
    " }
    }
    expect "]#" { send "useradd jj
    " }
    expect "]#" { send "echo jiajie|passwd --stdin jj
    " }
    expect "]#" { send "exit
    " }
    expect eof
    EOF
    

    执行后的输出结果:

    [root@localhost shell.sh]# ./test.sh 192.168.1.106 root jiajie
    spawn ssh -l root 192.168.1.106
    root@192.168.1.106's password: 
    Last login: Sat Sep  9 04:10:46 2017 from web
    [root@localhost ~]# useradd jj
    [root@localhost ~]# echo jiajie|passwd --stdin jj
    Changing password for user jj.
    passwd: all authentication tokens updated successfully.
    [root@localhost ~]# exit
    logout
    Connection to 192.168.1.106 closed.
    [root@localhost shell.sh]# 
    

    五. shell脚本调用expect(2)

    通过shell脚本通过调用expect脚本实现批量认证:

    expect脚本:

    [root@localhost shell.sh]# vim scp.exp
    
    #!/usr/bin/expect
    if {$argc!=3} {
            send_user "Usage:expect need three arguments lisk thks:file host dir
    "
            exit 1
    }
    set srcname [lindex $argv 0]
    set hostname [lindex $argv 1]
    set destname [lindex $argv 2]
    set password "jiajie"
    spawn scp $srcname root@$hostname:$destname
    set timeout 30
    expect {
    #        -timeout 2
            "yes/no" {send "yes
    ";exp_continue}
            "*password:" {send "$password
    "}
    #        timeout {puts "expect connect failure,please contact admin.";return}
    }
    expect eof
    exit -onexit {
            send_user "Jobs has finished,Goodbye.
    "
    }
    

    shell脚本:

    [root@localhost shell.sh]# vim scp.sh 
    
    #!/bin/bash
    if [[ "$#" != "2" ]];then
            echo "Usage:$0 src_filename des_filename"
            exit 0
    fi
    IP_LIST=(
            192.168.1.106
            192.168.1.170
            192.168.1.10
    )
    . /etc/init.d/functions
    for ip in ${IP_LIST[*]}
    do
            expect scp.exp $1 $ip $2 &> /dev/null
            if [ $? -eq 0 ];then
                    action "$ip" /bin/true
            else
                    action "$ip" /bin/false
            fi
    done
    

    scp.sh脚本通过调用expect脚本来实现分发功能。执行结果如下:

    [root@localhost shell.sh]# sh  scp.sh  /etc/fstab /tmp/
    192.168.1.106                                              [  OK  ]
    192.168.1.170                                              [  OK  ]
    192.168.1.10                                               [FAILED]
    

    因为并没有192.168.1.10所有报错。

  • 相关阅读:
    七、Struts2之文件上传与下载
    八、Struts2之OGNL
    五、Struts2之类型转换
    wpf坐标转换相关
    wpf拖拽封装类
    获取Bitmap的Graphics
    Win32定时器
    vs2010调试dll
    使用GDI+ 保存HDC为位图文件
    在c++中使用.net
  • 原文地址:https://www.cnblogs.com/dianel/p/10315258.html
Copyright © 2011-2022 走看看