• expect tcl 摘录


    部分参考来源说明

    Expect 手册中文版
    Expect学习笔记
    tcl英文手册

    例子

    #!/usr/bin/expect
    # ssh
    # send_user -- 用来避免后面出现以-开头的用户提示信息被解释成非法参数
    #send_user -- "---------------------------------
    "    
    if { $argc < 4 } {
        send_user " ERROR : Invalid arguments.
    "
        send_user " Usage : $argv0 host user pw cmd
    "
        exit 10
    }
    
    set host [ lindex $argv 0 ]
    set user [ lindex $argv 1 ]
    set pw   [ lindex $argv 2 ]
    set cmd  [ lindex $argv 3 ]
    set timemout 15
    
    spawn ssh $user@$host $cmd
    # 获取spawn_id
    set ssh_id $spawn_id
    
    #  Note : exp_internal要位于spawn后, 0表示关闭调试模式,非0表示开启调试模式 , -f file表示调试内容写入文件。
    #         组合使用时: exp_internal -f file 0 ,后面的0表示调试信息仅仅写到文件,如果后面是1则调试信息写入文件同时输出到stdout
    exp_internal -f /tmp/exp_exec.log 0
    
    expect {
        -nocase "yes/no" {
            exp_send "yes
    "
            # Notice : exp_continue必须处于expect内,它能让expect再次从第一次匹配
            exp_continue
        }
        -nocase "password:" {
            exp_send "${pw}
    "
    	expect  "try again" {
    		send_user "
    ERROR: Password is incrrect!
    "
    		# close不带参数时默认关闭当前spawn_id
    		close $ssh_id
    		exit 12
    	}
        }
    
        # Note: default 包含了timeout和eof
        default {
            send_error "ERROR : timeout or eof.
    "
            close $ssh_id
            exit 11
       }
    }
    
    

    expect命令

    核心命令有三个 spawn、expect、send

    • spawn用于启动一个进程
      -ignore选项用于忽略信号,例如: spawn –ignore SIGINT –ignore SIGHUP ping $host #就会屏蔽发送给ping进程的中断和挂起信号
    • expect用于匹配
        用法1: 
            expect 表达式 {动作} 表达式 {动作} ...   
        用法2:
            expect {
                表达式 {动作}
                表达式 {动作}
                ...
            }
        
        两种用法是一样的,但是第二种用法格式比较清晰
        
        使用expect_before或expect_after偷懒:
            修改前:
            expect {
                "done" { puts "Done" }
                "p1" { puts "p1" }
            }
            expect {
                "done" { puts "Done" }
                "p2" { puts "p2" }
            }
            修改后:
            expect_before “done” { puts "Done" }
            expect {
                "p1" { puts "p1" }
            }
            expect {
               "p2" { puts "p2" } 
            }
        如果上面第二个expect块后面还有expect_before,则后面的expect_before会覆盖前面的expect_before。当然如果上面每个expect块中都有"done"表达式,那么块内的优先级会比expect_before的要高
    
    • send 用来发动作的,也可以使用exp_send命令(exp_send是send的别名)。 exp_send有两个选项:-i和-s,选项具体含义看后面说明。支持八进制和十六进制发送,比如exp_send " " 可以写成 exp_send "15"或exp_send "x0d"

    其他expect命令

    • expect_user匹配用户输入,而前面的expect是匹配程序输出的。
        expect_user {
            -re {[cC]hina} { puts stdout "中国" }
            -re {[jJ]apan} { puts stderr "日本" }
        }
        上面的例子是如果用户输入china/China就打印"中国",输入japan/Japan就打印"日本"
    
    • exp_continue 是expect块中的动作,作用就是从块的开始部分重新匹配表达式
    • exp_internal 调试命令。
        exp_internal  0      关闭调试。
        exp_internal  1      开启调试,输出到标准输出中。
        exp_internal –f file 0  调试信息写入文件,但不写到标准输出。
        exp_internal –f file 1  调试信息写入文件,也写到标准输出。
    
    • exp_pid 这个命令用于获取spawned启动的进程的进程
      ID号,注意exp_id不是spawn_id。
        set pid0 [ exp_pid –i $spawn_id ]  #使用exp_pid获取spawned进程id,并赋值给pid0变量
        send_user "spawned进程的pid是[ exp_pid –i $spawn_id ]
    " #打印spawned进程的id
    
    • send_user 相对于send,exp_send发送数据给进程,send_user是发送数据给标准输出。send_error是类似的命令,只不过输出到标准错误
    • send_log 命令输出到日志文件中。需要配合log_file命令使用
    • log_file 命令用来将输出记录到一个文件中去,使用格式如下:
        log_file  <选项>  文件名 当这个命令带有文件名时,表示将spawn程序的标准输出记录到文件中(我测试的结果是send_user的文本也进来了),只使用log_file命令但不带文件名则表示关闭记录。
        
        log_file的选项:
        -leaveopen 当文件已经被打开时,不继续向这个文件中添加内容。
        -noappend  如果文件已存在,那么清空文件中的内容,然后再写入。
        -a         如果文件已存在,则将新内容附加到当前文件的末尾。
    
    • log_user 命令,log_user 0 表示关闭spawn的所有输出,log_user 1表示spawn输出到标准输出。不太确定,还是贴上man手册
        log_user -info|0|1
                 By default, the send/expect dialogue is logged to stdout (and a logfile if open).  The logging to stdout is disabled by the command "log_user 0" and reenabled by "log_user 1".   Logging  to
                 the logfile is unchanged.
    
                 The -info flag causes log_user to return a description of the most recent non-info arguments given.
    
    • 总结一下上面的输出:主动使用send_user或send_error的输出,主动使用send_log写文件的输出。还有使用log_user控制spawn send/expect是否输出到标准输出

    • close close命令用来关闭连接,它支持-i选项,用来关闭指定句柄的过程,如果不带任何选项,则关闭当前$spawn_id变量指定的过程。

    • wait wait命令与close命令相似,都是用来关闭连接的,但wait命令是等待系统主动返回eof,也就是结束信号后才关闭,而不是像close那样无条件关闭,与close命令一样,它也支持-i选项。

    • remove_nulls expect中,默认会去掉返回中的控制符,注意:不要将控制符与空白符搞混,控制符主要是信号,他们是不会显示在屏幕上的,比如使用ctrl+c(中断)、ctrl+d(终止)等组合键发送的信号,信号是ASCII码表中01-31区间中的字符;空白符则是可以显示出来的空白符号,比如空格、回车、换行、制表等一系列符号。
      remove_nulls命令可以控制是否去掉返回中的控制符,使用方法如下:
      remove_nulls 0 #关闭自动去掉控制符的功能
      remove_nulls 1 #开始知道去掉控制符的功能,这是默认值。

    • match_max 用来设置expect_out(buffer)变量的缓存大小,默认情况下expect_out(buffer)变量缓存是2000个字符,你可以设置这个大小来设置更符合实际的缓存,使用方法如下:match_max 65535 支持-i或-d选项,-i和-d见本文的选项介绍

    • trap 信号处理,语法是 trap [[command] signal], 例如expect默认有:trap exit {SIGINT SIGTERM}

        1-捕获到SIGINT HUP QUIT信号后,打印信号名和信号数值
        trap {
           send_user "signal name is [trap –name]
    "  # -name选项用来显示信号名
           send_user“signal integer is [trap –number]” # -number选项显示信号数值
           exit
        } {SIGINT SIGHUP SIGQUIT} 
        
        2-取消某些信号
         trap SIG_IGN { SIGINT SIGHUP SIGQUIT}
        
        3-恢复信号的默认处理
        trap SIG_DFL { SIGINT SIGHUP SIGQUIT }
    
    • exit 退出命令,语法 exit [-opts] [status]。
        exit –onexit {
           send_user“Good bye
    ”
        }
        # -onexit选项后面可以跟onexit的handler,做扫尾工作。这些命令都可以man expect找到说明
    
    • interact 该命令是Expect中非常重要的命令之一,它用来在脚本中将控制权交给用户,由用户与spawn生成的进程进行交互。细节可以man expect
         例子:  # 输入完密码后,用户可以和远端shell交互,按q或ctrl+D将控制权重新还给脚本
        spawn ssh root@192.168.1.111
        interact {
            "q"     {return} 
            "04"  {return}    # ascii 004是EOT 也就是ctrl+D
        }
        
        expect {
            ....
        }
    
    • interpreter 调用解释器,可以用于调试,比如puts变量内容。调试完后,可以使用return返回

    expect命令的选项

    • -d选项 几乎所有expect命令都支持-d选项,d代表default,也就是设置某些命令的默认值,比如:
      remove_nulls –d 1
      timeout –d 30 #设置默认超时
    • -i选项 一般用于同时控制多个spawn进程。
      1.例如spawn好几个进程,每个spawn后面通过类似 set sp_id0 ${spwan_id}的命令 获取操作这个spawn进程的句柄。后面通过这个spawn id来控制,例如 exp_send -i ${sp_id0} "commmand1
    " 
      2.再例如,在expect的过程中使用spawn id才针对性匹配。比如:
        spawn ./hotpotcmd
        set hid ${spawn_id}
        spawn  ./barbecure
        set bid ${spawn_id}
        expect {
    	    -i $hid
    	    -re {hot[pP]ot} { send_user "hotpot ok
    " }
        }
        expect {
    	    -i $bid
    	    -re {[bB]arbecure} { send_user "barbecure ok
    " }
        }
    
    • -f选项,f代表 file ,某些Expect命令支持这个选项,比如exp_internal命令,这个选项用来将某些命令的输出放入一个文件中去,因此这个选项后面必须带有文件的路径作为值。
    • -s选项
      s代表slowly,也就是发送速度,这个选项一般用于send族命令中,比如send、exp_send、send_user、send_error等等,使用这个选项之前,必须先对send_slow变量赋值,send_slow变量设置expect发送字符的速度,它接受2个参数,一个是字符个数,另一个是时间,使用方法如下:
      set send_slow {character seconds}
      第一个参数是字符个数,第二个是时间,单位为秒,比如:set send_slow {10 1} 表示每秒钟发送10个字符,当然如果生效,send命令必须加上-s参数,比如:set send_slow {10 1}; send -s “hello ”
    • -h选项 代表human,用来模拟人敲击键盘的动作,可以用于所有send命令族,比如exp_send、send_user等等,使用之前必须先对send_human变量赋值。例如:set send_human {.1 .5 1 .05 2} 四个参数分别表示:.1每个字母输入的平均间隔(0.1秒).5表示单词输入完后停顿时间。1表示间隔时间变化的剧烈程度,取值0到无穷大,1表示比较合理的,需要结合最后两个参数。.05表示输入字符最小间隔时间,2表示输入字符最大间隔时间。
    • -gl选项,代表global,用于指定全局类型的表达式,用于expect、interact命令族中,比如expect、expect_user、expect_error等,global形式的表达式与DOS的通配符相似,用*表示任意多个任意字符,?表示一个任意字符,这是一种很简单的表达式
    • -ex选项,代表exact,用于指定精确类型的表达式,用于expect、interact命令族中,这种类型的表达式特点就是所有字符都精确代表它本身的含义,不存在通配符。
    • -re选项代表regular expression,也就是正则表达式,用于expect、interact命令族中
    • -null选项,这个选项可以用于expect和send过程,用于expect时表示连同空字符也一样做匹配(默认情况下不匹配),用于send则用于发送空字符,在send命令中还可以一次发送多个空字符,比如:send –null 3
    • -ignore选项,这个选项用于spawn命令,用来忽略某些特殊的信号,比如忽略ctrl+c和ctrl+d:spawn–ignore SIGINT –ignore SIGHUP ping $host
    • -info选项用于expect_before和expect_after命令中,用于对这两个命令的调试
    • -onexit见上面的exit命令,-number和-name选项见trap命令,这里省略
    • --选项,表示选项的终止

    变量

    • expect_out(buffer),数组,这个变量中放置从上一次匹配到这一次匹配之间的所有返回,包括匹配字符本身。
    • spawn_id 专门用于expect中的进程管理

    tcl摘录

    数据类型

    • tcl只有一种数据类型--字符串

    符号

    • $ 变量展开(substitution). $var或${var}是标量变量展开,$var(index)是数组变量展开
    • [] 方括号,命令展开,也就是执行括号内的命令,例如set kernel [ exec bash -c {uname -r} ] # kernel的值为内核版本号
    • " 双引号把词组标记为命令的一个参数. 注意:"$"符号和方括号在双引号内仍被expect解释
    • { } 大括号也把词组标记为命令的一个参数. 但是, 其他符号在大括号内不被解释(保持原样)
    • 反斜线表示转义,支持八进制、16进制、unicode: ooo xhh uhhhh

    命令

    • 参考 http://www.tcl-lang.org/man/tcl8.6/TclCmd/contents.htm,下面只摘录部分
    • set 用于变量赋值,unset用于清除变量。 例如set var "xxxx" #普通变量; set week(mon) 1 #赋值数组; set d [expr 10+15]
    • expr
    • format 类似于c的sprintf。例如 set var [ format "year=%s mon=%s" $year $mon]
    • scan 类似c的sscanf。例如 scan "some 26 34" "some %d %d" a b
    • regexp 正则匹配。语法 regexp [switchs] [--] expr_string [matchVar] [submatchVar] [submatchVar]...
      switch支持 -nocase -line
        regexp {(cn|jp|kr) +([0-9]+) km} "cn 4022 km" all country num 
        puts "all=$all country=$country num=$num"
        回显:all=cn 4022 km country=cn num=4022
    
    • append 追加到变量,例如 set var "af"; append var ":01" ":b3" #则var值为"af:01:b3"
    • lappend — Append list elements onto a variable
    • lassign 列表赋值
        lassign {a b c} x y z       ;# Empty return
        puts $x                     ;# Prints "a"
        puts $y                     ;# Prints "b"
        puts $z                     ;# Prints "c"
    
    • linsert 列表插入,参考手册
    • lindex 列表取值(可以多个),参考手册
    • 其他列表操作: list, lappend, linsert, llength, lsearch, lset, lsort, lrange, lreplace, string 自己参考
    • dict 字典,
    • join 合并
    • expr 数学计算
    • if
        if {$vbl == 1} {
           puts "vbl is one"
        } elseif {$vbl == 2} {
            puts "vbl is two"
        } else {
            puts "vbl is not one or two"
        }
    
    • for和foreach
        for {set x 0} {$x<10} {incr x} {
            puts "x is $x"
        }
        
        set x {}
        foreach {i j} {a b c d e f} {
            lappend x $j $i
        }
        # The value of x is "b a d c f e"
        # There are 3 iterations of the loop.
        The next loop uses i and j to iterate over two lists in parallel.
    
        set x {}
        foreach i {a b c} j {d e f g} {
            lappend x $i $j
        }
        # The value of x is "a d b e c f {} g"
        # There are 4 iterations of the loop.
    

    其他说明

    • log_user 命令用来指定Expect输出的位置,默认情况下log_user的值是1,表示所有输出都放在标准输出中(一般是显示器,如果采用重定向也可以定位到文件中),如果将这个值赋值为0就表示不需要任何输出。

    • log_file 命令用来将输出记录到一个文件中去,使用格式如下:
      log_file <选项> 文件名
      选项包括下面几种:
      -open当一个文件已经被打开时,使用这个选项可以往这个文件里继续添加内容,这个选项一般用于windows系统,因为windows系统中文件是独占的,Linux系统中就不存在这个问题了。
      -leaveopen当文件已经被打开时,不继续向这个文件中添加内容。
      -noappend如果文件已存在,那么清空文件中的内容,然后再写入。
      -a如果文件已存在,则将新内容附加到当前文件的末尾。当这个命令带有文件名时,表示将spawn程序的标准输出记录到文件中,只使用log_file命令但不带文件名则表示关闭记录,这样你就可以只记录自己感兴趣的部分了。

    • remove_nulls
      expect中,默认会去掉返回中的控制符,注意:不要将控制符与空白符搞混,控制符主要是信号,他们是不会显示在屏幕上的,比如使用ctrl+c(中断)、ctrl+d(终止)等组合键发送的信号,信号是ASCII码表中01-31区间中的字符;空白符则是可以显示出来的空白符号,比如空格、回车、换行、制表等一系列符号。
      remove_nulls命令可以控制是否去掉返回中的控制符,使用方法如下:
      remove_nulls0# 关闭自动去掉控制符的功能
      remove_nulls1# 开启自动去掉控制符的功能,这是默认值

    • 含有””(和-re “.”)的模糊匹配的模式会清空输出缓冲区,不再读取从进程中输出的字符。更多关于输出缓冲区的说明

  • 相关阅读:
    C#处理Json文件
    突袭HTML5之WebSocket入门1 WebSocket协议
    突袭HTML5之Canvas 2D入门3 变换与组合
    突袭HTML5之Canvas 2D入门5 事件与动画
    Ruby札记1 安装、运行
    突袭HTML5之WebSocket入门4 开发框架express
    突袭HTML5之Canvas 2D入门4 直接操作像素
    Excel VBA 学习总结 实战之惑
    突袭HTML5之WebSocket入门2 高效服务器Node.js
    自定义xtraGrid mater/ detail 数据结构显示
  • 原文地址:https://www.cnblogs.com/mind-water/p/12106101.html
Copyright © 2020-2023  润新知