expect主要应用于自动化交互式操作的场景;比如服务器过多,密码也不尽相同的情况下,需要便捷的登陆服务器,而无需输入密码的情况,亦或者便捷登陆mysql/ftp等需要交互的场景;也可以在服务器之间通过scp传输文件而不需要输入密码的场景;
安装expect
  CentOS:yum install expect -y
  Mac:brew install expect
  脚本后缀为exp
常用命令介绍
  send 接收一个字符串,并将该字符串发送到进程;
  expect 从进程接收字符串,根据进程反馈发送相应的交互命令,比如ssh登陆需要到输入密码的那步(password:);
  spawn 启动新的进程,来执行相应的命令;
  interact 允许用户交互,比如ssh登陆或者ftp登陆mysql登陆,加上interact参数则spawn启动的进程执行完成之后仍然停留在ssh/ftp/mysql的交互界面而不退出;
基本语法
1、方括号[cmd]
  执行一个嵌套命令,例如想传递一个命令的结果作为另一个命令的参数则使用[ ];
2、双引号“ ”
  $符在“ ”中仍然被解释,意思是可以进行变量替换;
  puts "please enter number: $num"
3、设置变量
  set name "zhang"
  变量名name
4、输出使用puts
5、运算expr
  expr $i/5
  可以使用+ - * /和%作为基本运算符;还有一个运算符incr,表示对变量加1;
6、$argv 参数数组
  通过 [lindex $argv n] 可以获得第 n 个参数的值
7、exp_continue
  跟在某个 expect 判断项之后,可以使该项被匹配后,还能继续匹配该 expect 判断语句内的其他项,比如首次登陆Linux服务器需要先yes才能再输入密码,如果不加exp_continue则yes输入完成之后,会停在那,不再走输入密码的交互;
8、set timeout
  设置超时时间,单位秒,假如配置为30,则某个 expect 判断未能成功匹配的 30 秒后,将跳过该 expect 判断,执行后续内容。可以设置为-1,表示无限制。
9、log_file
  将expect在控制台的输出信息写入指定的文件中;
  log_file out.log
常用参数
  -d 用于跟踪脚本的执行过程,类似于shell脚本的bash -x效果;
  -f 一般写在脚本最上面定义使用方法的时候才有用(#!/usr/bin/expect -f);实际作用尚不明确;
for循环
方法一:
#!/usr/bin/expect
foreach i { 1 2 3 4 5 } {
puts "$i"
}
方法二:
#!/usr/bin/expect
for {set i 0} {$i < 10} {incr i} {
puts "$i"
}
while循环
set i 0
while {$i < 10} {
puts "$i"
incr i
}
if语句
  就拿我在实际应用中用的便捷登陆设备的脚本举例;在实际中我将该脚本的执行做成了别名的形式,运行的时候通过“别名 参数”的方式执行,很方便;
alias ai="/Users/zhangzhide/shen-project/ai-project.exp" #定义别名
ai 191 #通过别名登陆191这台设备
#!/usr/bin/expect
set timeout 2
set ip [lindex $argv 0]
set aixin221 "Password221"
set aixin191 "Password191"
if { $ip == 191 } {
  spawn ssh root@100.13.0.$ip
  expect {
    "*yes/no*" { send "yes\r"; exp_continue }
    "*password:" { send "$aixin191\r" }
    }
  interact
  } elseif { $ip == 221 } {
  spawn ssh root@100.13.0.$ip
  expect {
    "*yes/no*" { send "yes\r"; exp_continue }
    "*password:" { send "$aixin221\r" }
    }
  interact
  } else {
  puts "please enter true ipaddr:
    191 后端
    221 前端页面"
  }
函数
proc my_proc {i} {
​ puts $i;
​ } ​​
在shell脚本中调用expect
#!/bin/bash
/usr/bin/expect << EOF
#在shell中调用expect
spawn ssh root@192.168.100.10
  expect {
    "*yes/no*" { send "yes\r"; exp_continue }
    "*password*" { send "123\r" }
  }
  interact
  EOF
scp传输举例

#!/usr/bin/expect
set timeout 10
set host [lindex $argv 0]
set username [lindex $argv 1]
set password [lindex $argv 2]
set src_file [lindex $argv 3]
set dest_file [lindex $argv 4] spawn scp $src_file $username@$host:$dest_file expect {
"*yes/no*" { send "yes\r"; exp_continue }
"*password:" { send "$password\r" } } interact

执行脚本:/data/copy.exp 192.168.21.4 root 'wO0]Dcg;y' /data/m3u8.gz /data/m3u8.gz

注意:如果密码中包含特殊字符,需要用单引号引起来;

便捷登陆mysql举例
#!/usr/bin/expect
spawn mysql -h 10.10.0.36 -u root -p
expect "*password:"
send "123.com\r"
interact

批量导出mysql表结构应用
  公司要搭一个新环境,需要用到老库的表结构,由于连接老库需要vpn,无法在CentOS服务器上通过mysqldump连接老库导表,只能通过个人电脑了,但是mac比较傲娇的是不支持(mysqldump -p PASSWD)直接将密码跟在-p参数后面的操作,50多个表啊,我不能一个一个的去输入密码,因此想到了expect;
具体操作方法如下:
  1、先建立一个文件,将所有表名写入文件中;
    vim table
    table1
    table2
    ...
    table56
  2、写expect脚本
    #!/usr/bin/expect
    set table [lindex $argv 0]
    spawn mysqldump -h 10.10.0.23 -u root -p old_dat $table
    expect "*password:"
    send "123.com\r"
    interact
  3、用shell脚本调用expect脚本
    for i in `cat table`;do echo `./table.exp $i > $i.sql`;done
  这时候要问了,为什么不在expect中写for循环直接导出表呢?我这么尝试过,发现导不出来,后来查资料才知道spawn不支持标准输出;所以在expect脚本中无法实现,于是就想到了上面的方法,通过shell去调用expect脚本;由于时间紧,任务重,也就没管好不好看,好用就行;
  注意:这么导出来的sql表仍然是不能用的,在导出的每个表中都会有一些额外的输出信息,好在它们在每个表中长得都一样,所以请出文本三剑客之一的sed批量处理一下就好啦;

expect交互学习笔记的更多相关文章

  1. 【转】expect语言学习笔记

       上周mentor要求我写一个unix shell 脚本, 以便半夜让服务器自动编译image. 其实我觉得每天我走的时候让服务器编译不也挺好的么... 我懒,假装没听见好不容易赖过去了.     ...

  2. iOS与Html5和JS之间的交互---学习笔记五

    首先采用的框架是WebViewJavascriptBridge,采用这套框架可以方便的使iOS与JS交互 一. 流程图(主要介绍思路) 二.iOS端如何使用 首先导入#import "Web ...

  3. expect学习笔记及实例详解【转】

    1. expect是基于tcl演变而来的,所以很多语法和tcl类似,基本的语法如下所示:1.1 首行加上/usr/bin/expect1.2 spawn: 后面加上需要执行的shell命令,比如说sp ...

  4. MiZ702学习笔记13——ZYNQ通过AXI-Lite与PL交互

    在<MiZ702学习笔记7——尝试自制带总线IP>,我曾提到了AXI4-Lite的简单用法,驱动了下流水灯,只涉及到了写总线.今天,我想利用之前的VGA模块,将AXI4-Lite的读写都应 ...

  5. HTML+CSS学习笔记(5)- 与浏览者交互,表单标签

    HTML+CSS学习笔记(5)- 与浏览者交互,表单标签 1.使用表单标签,与用户交互 网站怎样与用户进行交互?答案是使用HTML表单(form).表单是可以把浏览者输入的数据传送到服务器端,这样服务 ...

  6. Django学习笔记(8)——前后台数据交互实战(AJAX)

    这里将自己这段时间学习的关于前后台数据交互的笔记写在这里,这里包含了Django传输数据给JS,AJAX的相关问题,跨域问题,如何解决AJAX的跨域问题等等.比较凌乱,请看到这篇博客的盆友见谅,如果我 ...

  7. #学习笔记#JSP数据交互

    #学习笔记#JSP数据交互 数据库的使用方式:   当用户在第一个页面的查询框输入查询语句点提交的时候我们是用什么样的方式完成这个查询的? 答:我们通过在第一个页面提交表单的形式,真正的数据库查询时在 ...

  8. expect学习笔记及用法

    expect学习笔记及实例详解 expect的基本用法 expect用法

  9. SpringBoot学习笔记(4):与前端交互的日期格式

    SpringBoot学习笔记(4):与前端交互的日期格式 后端模型Date字段解析String 我们从前端传回来表单的数据,当涉及时间.日期等值时,后端的模型需将其转换为对应的Date类型等. 我们可 ...

随机推荐

  1. CSS 不规则的轮廓-outline

    大家好,我是半夏,一个刚刚开始写文的沙雕程序员.如果喜欢我的文章,可以关注 点赞 加我微信:frontendpicker,一起学习交流前端,成为更优秀的工程师-关注公众号:搞前端的半夏,了解更多前端知 ...

  2. Spring事务源码解读

    一.Spring事务使用 1.通过maven方式引入jar包 <dependency> <groupId>com.alibaba</groupId> <art ...

  3. unity---点击事件

    点击事件 点击触发的事件脚本 脚本挂载方式 On Click() 如果点击后触发,调用Button物体下,Button_lick脚本中的func函数/func_text 结果

  4. v86.01 鸿蒙内核源码分析 (静态分配篇) | 很简单的一位小朋友 | 百篇博客分析 OpenHarmony 源码

    本篇关键词:池头.池体.节头.节块 内存管理相关篇为: v31.02 鸿蒙内核源码分析(内存规则) | 内存管理到底在管什么 v32.04 鸿蒙内核源码分析(物理内存) | 真实的可不一定精彩 v33 ...

  5. 【Java面试】什么是幂等?如何解决幂等性问题?

    一个在传统行业工作了7年的粉丝私信我. 他最近去很多互联网公司面试,遇到的很多技术和概念都没听过. 其中就有一道题是:"什么是幂等.如何解决幂等性问题"? 他说,这个概念听都没听过 ...

  6. [CSP-S 2019 Day2]Emiya家今天的饭

    思路: 这种题目就考我们首先想到一个性质.这题其实容易想到:超限的菜最多只有一个,再加上这题有容斥那味,就枚举超限的菜然后dp就做完了. 推式子能力还是不行,要看题解. 式子还需要一个优化,就是废除冗 ...

  7. Python趣味入门9:函数是你走过的套路,详解函数、调用、参数及返回值

    1.概念 琼恩·雪诺当上守夜人的司令后,为训练士兵对付僵尸兵团,把成功斩杀僵尸的一系列动作编排成了"葵花宝典剑法",这就是函数.相似,在计算机世界,一系列前后连续的计算机语句组合在 ...

  8. golang 方法接收者

    [定义]: golang的方法(Method)是一个带有receiver的函数Function,Receiver是一个特定的struct类型,当你将函数Function附加到该receiver, 这个 ...

  9. Python工程:ImportError: attempted relative import with no known parent package

    Python工程:ImportError: attempted relative import with no known parent package 解决方法: 1.对每个目录创建的时候都选择创建 ...

  10. 是时候为Spring Boot 3.0做准备了

    2018年2月28日Spring Boot进入2.0时代,距今已经超过4年了. 2022 年 11 月 Spring Boot 3.0 将正式发布,它将基于 Spring Framework 6.0, ...