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

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

作者头像
qsjs
发布2020-06-09 09:05:10
8120
发布2020-06-09 09:05:10
举报

我们已经知道expect可以帮我们自动完成“交互工作”,但是如果我们需要拿到 通过expect spawn的sub-process 所执行命令的结果,那么怎么做呢? 通过重定向当然是不可能的了,因为spawn产生的是一个由expect来维护的一个子进程,当这个sub-process结束的时候,已经没有办法再进入了,就算重定向成功,也是无法拿到结果,况且重定向是否成功,我们也是没有办法知道的; expect给我们提供了一个特定的访问方法,那就是用 expect_out, 常用的有$expect_out(buffer) 或者 $expect_out(NUMBER, string) , 把 $expect_out(buffer) 或者 $expect_out(NUMBER, string) 的结果通过set 赋值给变量,然后把变量写入文件就可以拿到命令的执行结果了;

要使用expect_out, 我们必须首先理解expect_out. 这里介绍expect_out到底保存了什么?

当expect执行匹配验证的时候,它是 把sub-process的输出作为 被查找的对象,而用户提供的“匹配关键字或者正则表达式” 作为“查找对象”,那么被查找对象总是sub-process从头开始的所有输出吗? 当然不是,”被查找对象“总是从前一次匹配的位置开始(不含已经匹配的内容),一直到sub-process的最新输出;每一次expect的匹配都是如此执行的,这时候如果匹配到了,那么就会把前一次匹配位置开始 到当前匹配的位置结束,把这中间的内容保存下来,这个结果可以通过 $expect_out(buffer) 来访问到. 如果没有匹配到,$expect_out(buffer)的结果是不会更新的; 这一段理解起来有一点拗口,不过对使用 expect_out非常重要,我们通过下面的例子进行验证:

代码语言:javascript
复制
[root@instance-6p8qz002 ~]# cat t.sh
#!/bin/bash
for i in `cat t.txt`;do
        ofile=$i                    #用于设置文件名称;
        expect <<-EOF
        log_file ./exp_log   #开启expect的log, 只需要指定 log_file 变量就可以了,很方便是不是?
        set output [open $ofile w]      #以w的方式打开文件
        spawn ssh test_user@$I      
        expect "assword"      #第一次进行expect, 匹配到就输入密码;
        send "$1\r"         #输入密码;
        expect "~]"   #第二次进行expect匹配
        send "\r"
        set outcome \$expect_out(buffer)   #此时获取$expect_out(buffer)的值,就是前面第一次匹配到第二次匹配之间的内容;我们写入到文件中,随后进行验证;
        puts \$output \$outcome  #把内容写入文件
        expect eof
        exit
EOF
done


#执行上面脚本,这里忽略执行过程;
#查看执行结果:localhost 文件的内容是通过 脚本把$expect_out(buffer)的内容保存下来的结果,而exp_log文件的内容是expect的日志文件,日志文件里面记录了sub-process的所有输出;
[root@instance-6p8qz002 ~]# cat localhost
:
Last login: Fri Oct 11 20:42:19 2019 from ::1
[test_user@instance-6p8qz002 ~]


#查看expect的log文件;
[root@instance-6p8qz002 ~]# cat -n exp_log
     1  spawn ssh test_user@localhost
     2  test_user@localhost's password:
     3  Last login: Fri Oct 11 20:42:19 2019 from ::1
     4  [test_user@instance-6p8qz002 ~]$
     5  [test_user@instance-6p8qz002 ~]$ 
[root@instance-6p8qz002 ~]#

从上面的expect的log文件exp_log中可以看到: 第一次调用expect匹配到第2行的assword,匹配字符串之后的字符是冒号; 第二次调用expect,是从第2行的冒号开始进行匹配的,一直到第4行,发现了匹配的字符串:~]; 根据前面的解释,从第一次匹配后的字符:”冒号“ 到 第二次匹配的字符串"~]"之间的内容,就应该是$expect_out(buffer) 的内容,这是根据exp_log ,通过manually分析出来的内容; 而在脚本中已经把 $expect_out(buffer)的结果存到文件localhost中了;手动分析的结果和脚本执行的结果一致,所以上述的解释是合理的;

下面修改脚本的内容,使第二次的匹配失败,看看$expect_out(buffer)的结果:

代码语言:javascript
复制
#把上面脚本的第10行的内容修改为:expect "#]"  就可以了;
#运行脚本,并查看结果
[root@instance-6p8qz002 ~]# cat localhost
test_user@localhost's password
[root@instance-6p8qz002 ~]# cat -n exp_log
     1  spawn ssh test_user@localhost
     2  test_user@localhost's password:
     3  Last login: Fri Oct 11 20:49:06 2019 from ::1
     4  [test_user@instance-6p8qz002 ~]$
     5  [test_user@instance-6p8qz002 ~]$ 

因为第二次expect执行expect "#]" 进行匹配,结果当然是匹配不上,所以$expect_out(buffer) 的结果并没有更新,还是从spawn 开始到第一次匹配之间的内容,所以localhost的结果只有一条内容.

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

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 要使用expect_out, 我们必须首先理解expect_out. 这里介绍expect_out到底保存了什么?
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档