• 每次进步一点点——linux expect 使用


    1. 介绍

    expect是建立在tcl(参见:Tcl/Tk快速入门 )基础上的一个工具,它可以让一些需要交互的任务自动化地完成。相当于模拟了用户和命令行的交互操作。 
    一个具体的场景:远程登陆服务器,并执行命令 
    登录时输入密码需要交互,bash脚本无法完成,可以使用expect来完成。

    2. 安装

    下面介绍两种安装方式

    yum 安装

    yum install -y expect
    
    • 1
    • 2

    源码编译安装

    expect 依赖于 tcl, 所以需要首先安装 tcl。可以使用rpm检查是否已经安装tcl:

    rpm -qa | grep tcl
    
    • 1
    • 2

    如果已安装,则会打印出tcl软件信息

    安装过程参考:linux expect 安装 http://www.cnblogs.com/daojian/archive/2012/10/10/2718390.html 
    tcl 地址:https://sourceforge.net/projects/tcl/files/Tcl/ 选择一个版本 
    expect 地址:https://sourceforge.net/projects/expect/files/Expect/ 选择一个版本 
    注意:wget 下载的时候需要加上 –no-check-certificate, 不检查网站证书

    3. 原理与工作机制

    首先使用 spawn 开启一个会话,然后使用 expect-send 对来执行交互式操作。 
    spawn 后面跟上一个命令操作,表示开启一个会话。expect 等待输出特定的字符串(通常是提示符),然后使用send 发送交互字符串。比如:

    spawn ssh username@host # 远程登录
    
    expect "*assword" # 提示为:"username@host's password:", 等待用户输入密码
    send "${password}
    " # 这时使用send模拟用户输入密码的字符串,完成登录验证
    
    • 1
    • 2
    • 3
    • 4
    • 5

    4. 基本语法介绍

    脚本解释器

    脚本中首先引入文件,表明使用的是哪一个shell

    #!/usr/bin/expect
    
    • 1
    • 2

    set

    设置会话超时时间为30s, 若不限制超时时间则应设置为-1

    set timeout 30
    
    • 1
    • 2

    set 还可以设置变量

    # 使用变量语句:$param 或者 ${param}({}用来避免param和后面的字符串拼接起来导致错误)
    set param "param_str"
    set param 1
    
    • 1
    • 2
    • 3
    • 4

    spawn

    spawn 后面跟一个命令,开启一个会话

    spawn ${cmd} # for example : spawn su root
    
    • 1
    • 2

    expect - send

    expect 接收命令执行后的输出,然后和期望字符串匹配,若对应这执行相应的send来发送交互信息。

    expect "$case1" {send "$respond1
    "} # 这一行等同于下面两行
    
    expect "$case1"
    send "$response1
    "
    
    • 1
    • 2
    • 3
    • 4
    • 5

    expect 可以有多个分支,就像switch语句一样。

    expect 
    {
        "$case1" {send "$response1
    "}
        "$case2" {send "$response2
    "}
        "$case3" {send "$response3
    "}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    结束符

    expect eof :等待执行结束,若没有这一句,可能导致命令还没执行,脚本就结束了 
    interact : 执行完成后保持交互状态, 这时可以手动输入信息 
    注:expect eof 与 interact 二选一即可

    接收参数

    参数存在argv中,使用第一个参数如下:

    set param0 [lindex $argv 0]
    
    • 1
    • 2

    $argc表示参数个数,判断语句如下:

    if {$argc < 1} {
        #do something
        send_user "usage: $argv0 <param1> <param2> ... "
        exit
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    注:$argv0 是脚本名,但[lindex $argv 0]是第一个参数 param1, [lindex $argv 1]是第二个参数 param2, 以此类推 
    send_user 用来显示信息到父进程(一般为用户的shell)的标准输出。

    5. 实例

    实现远程登录服务器,并切换到root用户下执行关闭防火墙的命令,然后退出

    #!/usr/bin/expect
    
    if {$argc < 4} {
        #do something
        send_user "usage: $argv0 <remote_user> <remote_host> <remote_pwd> <remote_root_pwd>"
        exit
    }
    
    set timeout -1
    set remote_user [lindex $argv 0] # 远程服务器用户名
    set remote_host [lindex $argv 1] # 远程服务器域名
    set remote_pwd [lindex $argv 2] # 远程服务器密码
    set remote_root_pwd [lindex $argv 3] # 远程服务器根用户密码
    
    # 远程登录
    spawn ssh ${remote_user}@${remote_host}
    expect "*assword:" {send "${remote_pwd}
    "}
    expect "Last login:"
    
    # 切换到 root
    send "su
    "
    expect "*assword:" {send "${remote_root_pwd}
    "}
    
    # 执行关闭防火墙命令
    send "service iptables stop
    "
    send "exit
    "
    send "exit
    "
    expect eof
    

    将代码保存到 remot_root_command.exp 中,权限改为755,然后执行下面这条命令即可:

    ./remote_root_command.exp <remote_user> <remote_host> <remote_pwd> <remote_root_pwd>
  • 相关阅读:
    2011/6/24 数据库分析
    项目代码总结
    背景透明 by sofish
    ie6 reflow bug
    ID与CLASS的使用技巧
    CSS浮动属性Float详解 by 帕兰
    javascript闭包 by 李松峰
    详解CSS选择器、优先级与匹配原理
    垂直对齐:verticalalign属性 by ddcatlee
    行高lineheight,以及基线、顶线、中线和底线,还有内容区域、行内框和行框 by 豆豆猫的窝
  • 原文地址:https://www.cnblogs.com/ExMan/p/8447258.html
Copyright © 2020-2023  润新知