前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Here Documents 结合expect的使用--(3)

Here Documents 结合expect的使用--(3)

作者头像
qsjs
发布2020-06-09 09:03:50
4040
发布2020-06-09 09:03:50
举报
文章被收录于专栏:MyPanda的学习笔记

在上一节中,我们学习了 expect_out,但是还没有演示到底如何使用expect_out来获得spawn出来的sub-process中执行的命令的结果,这里我们来演示如下:

代码语言:javascript
复制
#我们这里来获取top命令的前10行结果,脚本内容如下:
[root@instance-6p8qz002 ~]# cat m.sh
#!/bin/sh
echo "" >./exp_log
for i in `cat t.txt`;do
        ofile=$i
        expect <<-EOF
        log_file ./exp_log
        set output [open $ofile w]
        spawn ssh test_user@$i
        expect "assword"
        send "$1\r"               
        expect "~]"
        send "top -bn 1 | head \r"
        send "\r"    #如果没有这一行,那么获取到的结果只有9行,而不是10行
        #如果不想用 send "\r"这一行,还想获得10行的输出怎么办?这时候,我们可以通过修改expect的表达式为: expect -re "~]"  来实现
        expect -re "(.*)\r\n(.*)\r\n(.*)~]"  
        set outcome \$expect_out(1,string)
        puts \$output \$outcome
        send "exit\r"
        expect eof
        exit
EOF
done
[root@instance-6p8qz002 ~]#
#top -bn1 |head 的结果保存在文件localhost中,查看localhost的结果:
[root@instance-6p8qz002 ~]# cat localhost
$ top -bn 1 | head
top - 12:11:54 up 7 days, 23:50,  8 users,  load average: 0.00, 0.01, 0.05
Tasks: 109 total,   2 running, 107 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.0 us,  0.0 sy,  0.0 ni,100.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  1014876 total,    81292 free,   190392 used,   743192 buff/cache
KiB Swap:        0 total,        0 free,        0 used.   591152 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND
    1 root      20   0  125476   3584   2236 S  0.0  0.4   0:08.30 systemd
    2 root      20   0       0      0      0 S  0.0  0.0   0:00.00 kthreadd
    3 root      20   0       0      0      0 S  0.0  0.0   0:54.61 ksoftirqd/0

在上面的脚本中, send "\r" 这一句非常重要,否则得到的结果只有9行,而不是10行,原因是什么呢? 如果没有send "\r" 这一行,我们可以看到exp_log的内容如下:

代码语言:javascript
复制
  1
  2 spawn ssh test_user@localhost^M
  3 test_user@localhost's password: ^M
  4 Last login: Sun Oct 13 12:11:54 2019 from ::1^M^M
  5 ^[[?1034h[test_user@instance-6p8qz002 ~]$ top -bn 1 | head ^M
  6 top - 12:21:44 up 8 days, 0 min,  9 users,  load average: 0.00, 0.01, 0.05^M
  7 Tasks: 111 total,   1 running, 110 sleeping,   0 stopped,   0 zombie^M
  8 %Cpu(s):  0.0 us,  0.0 sy,  0.0 ni, 93.3 id,  6.7 wa,  0.0 hi,  0.0 si,  0.0 st^M
  9 KiB Mem :  1014876 total,    77276 free,   193380 used,   744220 buff/cache^M
 10 KiB Swap:        0 total,        0 free,        0 used.   587960 avail Mem ^M
 11 ^M
 12   PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND^M
 13     1 root      20   0  125476   3584   2236 S  0.0  0.4   0:08.31 systemd^M
 14     2 root      20   0       0      0      0 S  0.0  0.0   0:00.00 kthreadd^M
 15     3 root      20   0       0      0      0 S  0.0  0.0   0:54.67 ksoftirqd/0^M
 16 [test_user@instance-6p8qz002 ~]$ exit^M
 17 logout^M
 18 Connection to localhost closed.^M^M

在脚本中的正则表达式为: (.*)\r\n(.*)\r\n(.*)~], 其匹配的内容分析如下: 1). 表达式的最后为 ~], 最大只能匹配到 16行的 ~] 2). 表达式匹配的开始位置为:第5行的$符号处 3). 在上述的5到16行之间,需要两个 换行符好进行分割,而实际上我们可以看到每一行都有一个换行符号,但是根据从前向后,每个(.*)都是尽可能的最大程度去匹配的原则,所以,第一个 (.*)匹配的就是 第5行的$到14行的末尾,而第二个(.*)匹配的就是15行,最后一个(.*)匹配的就是16行的开始到字符串“8qz002" 到这里,相信你已经get到了吧!!!是不是so easy ?

如果我们修改上述脚本,尝试发送的命令是: top -bn2 , 而不是top -bn1|head, 我们是否还可以获得期望的输出呢? 答案是否定的,因为 expect_out 并不是无限大的,当expect_out满了以后,就会丢弃匹配结果中前面的部分;那非要获得输出结果的全部应该怎么办呢? 当expect_out满的时候,会触发 full_buffer 的匹配,我们只需要对这个full_buffer的匹配进行处理,把expect_out的内容取出,然后再继续进行expect就可以了(通过exp_continue),代码如下:

代码语言:javascript
复制
#!/bin/bash
echo "" >./exp_log
for i in `cat t.txt`;do
        ofile=$i
        expect <<-EOF
        set outcome ""      #设置自定义的变量outcome.
        log_file ./exp_log
        set output [open $ofile w]
        spawn ssh test_user@$i
        expect "assword"
        send "$1\r"
        expect "~]"
        send "top -bn2\r"
        expect {                    #在此expect中可能触发 full_buffer,所以修改该段expect的代码
        full_buffer {              #添加对full_buffer匹配的处理;
                append outcome \$expect_out(buffer)  #在匹配full_buffer的时候,把结果追加到outcome中;
                exp_continue       #为了保证expect结构可以正常运行,这里需要用exp_continue确保full_buffer处理之后可以继续进行expect的处理;
        }
        -re "~]" {    #这里不建议采用分组的方式,因为分组不合适可能导致部分输出的内容丢失;
        append outcome \$expect_out(buffer)  #注意这里的append, 不能使用set ,否则会清空outcome中已经有的内容;  
        }
                }
        puts \$output \$outcome
        send "exit\r"
        expect eof
        exit
EOF
done

上面代码中,主要是通过 在原来的expect中添加 full_buffer 匹配的处理分支,在full_buffer匹配的时候,把结果追加到自定义的变量中,如果没有遇到full_buffer,那么也会把expect_out的内容转到 自定义变量中;从而通过自定义变量存储所有的输出结果;

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档