1. expect是基于tcl演变而来的,所以很多语法和tcl类似,基本的语法如下所示:
1.1 首行加上/usr/bin/expect
1.2 spawn: 后面加上需要执行的shell命令,比如说spawn sudo touch testfile
1.3 expect: 只有spawn执行的命令结果才会被expect捕捉到,因为spawn会启动一个进程,只有这个进程的相关信息才会被捕捉到,主要包括:标准输入的提示信息,eof和timeout。
1.4 send和send_user:send会将expect脚本中需要的信息发送给spawn启动的那个进程,而send_user只是回显用户发出的信息,类似于shell中的echo而已。

2. 一个小例子,用于Linux下账户的建立:
filename: account.sh,可以使用./account.sh newaccout来执行;

 1 #!/usr/bin/expect
 2
 3 set passwd "mypasswd"【这个是你设置的密码】
 4 set timeout 60
 5
 6 if {$argc != 1} {
 7     send "usage ./account.sh \$newaccount\n"
 8     exit
 9 }
10
11 set user [lindex $argv [expr $argc-1]]
12
13 spawn sudo useradd -s /bin/bash -g mygroup -m $user
14
15 expect {
16     "assword" {
17         send_user "sudo now\n"
18         send "$passwd\n"
19         exp_continue
20     }
21     eof
22     {
23         send_user "eof\n"
24     }
25 }
26
27 spawn sudo passwd $user
28 expect {
29     "assword" {
30         send "$passwd\n"
31         exp_continue
32     }
33     eof
34     {
35         send_user "eof"
36     }
37 }
38
39 spawn sudo smbpasswd -a $user
40 expect {
41     "assword" {
42         send "$passwd\n"
43         exp_continue
44     }
45     eof
46     {
47         send_user "eof"
48     }
49 }

View Code

3. 注意点:
第3行: 对变量赋值的方法;
第4行: 默认情况下,timeout是10秒;
第6行: 参数的数目可以用$argc得到;
第11行:参数存在$argv当中,比如取第一个参数就是[lindex $argv 0];并且如果需要计算的话必须用expr,如计算2-1,则必须用[expr 2-1];
第13行:用spawn来执行一条shell命令,shell命令根据具体情况可自行调整;有文章说sudo要加-S,经过实际测试,无需加-S亦可;
第15行:一般情况下,如果连续做两个expect,那么实际上是串行执行的,用例子中的结构则是并行执行的,主要是看匹配到了哪一个;在这个例子中,如果你写成串行的话,即
expect "assword"
send "$passwd\n"
expect eof
send_user "eof"
那么第一次将会正确运行,因为第一次sudo时需要密码;但是第二次运行时由于密码已经输过(默认情况下sudo密码再次输入时间为5分钟),则不会提示用户去输入,所以第一个expect将无法匹配到assword,而且必须注意的是如果是spawn命令出现交互式提问的但是expect匹配不上的话,那么程序会按照timeout的设置进行等待;可是如果spawn直接发出了eof也就是本例的情况,那么expect "assword"将不会等待,而直接去执行expect eof。
这时就会报expect: spawn id exp6 not open,因为没有spawn在执行,后面的expect脚本也将会因为这个原因而不再执行;所以对于类似sudo这种命令分支不定的情况,最好是使用并行的方式进行处理;
第17行:仅仅是一个用户提示而已,可以删除;
第18行:向spawn进程发送password;
第19行:使得spawn进程在匹配到一个后再去匹配接下来的交互提示;
第21行:eof是必须去匹配的,在spawn进程结束后会向expect发送eof;如果不去匹配,有时也能运行,比如sleep多少秒后再去spawn下一个命令,但是不要依赖这种行为,很有可能今天还可以,明天就不能用了;

4. 其他
下面这个例子比较特殊,在整个过程中就不能expect eof了:

#!/usr/bin/expectset timeout 30
spawn ssh 10.192.224.224
expect "password:"
send "mypassword\n"
expect "*$"
send "mkdir tmpdir\n"
expect "*$"

这个例子实际上是通过ssh去登录远程机器,并且在远程机器上创佳一个目录,我们看到在我们输入密码后并没有去expect eof,这是因为ssh这个spawn并没有结束,而且手动操作时ssh实际上也不会自己结束除非你exit;所以你只能expect bash的提示符,当然也可以是机器名等,这样才可以在远程创建一个目录。

注意,请不要用spawn mkdir tmpdir,这样会使得上一个spawn即ssh结束,那么你的tmpdir将在本机建立。

当然实际情况下可能会要你确认ssh key,可以通过并行的expect进行处理,不多赘述。

5. 觉得bash很多情况下已经很强大,所以可能用expect只需要掌握这些就好了,其他的如果用到可以再去google了。

6.实例:下面这个脚本是完成对单个服务器scp任务。

#!/usr/bin/expectset 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_fileexpect {"(yes/no)?"{send "yes\n"expect "*assword:" { send "$password\n"}}"*assword:"{send "$password\n"}}expect "100%"expect eof

注意代码刚开始的第一行,指定了expect的路径,与shell脚本相同,这一句指定了程序在执行时到哪里去寻找相应的启动程序。代码刚开始还设定了timeout的时间为10秒,如果在执行scp任务时遇到了代码中没有指定的异常,则在等待10秒后该脚本的执行会自动终止。

spawn代表在本地终端执行的语句,在该语句开始执行后,expect开始捕获终端的输出信息,然后做出对应的操作。expect代码中的捕获的(yes/no)内容用于完成第一次访问目标主机时保存密钥的操作。有了这一句,scp的任务减少了中断的情况。代码结尾的expect eof与spawn对应,表示捕获终端输出信息的终止。

有了这段expect的代码,还只能完成对单个远程主机的scp任务。如果需要实现批量scp的任务,则需要再写一个shell脚本来调用这个expect脚本。

#!/bin/shlist_file=$1
src_file=$2
dest_file=$3cat $list_file | while read line
dohost_ip=`echo $line | awk '{print $1}'`username=`echo $line | awk '{print $2}'`password=`echo $line | awk '{print $3}'`echo "$host_ip"./expect_scp $host_ip $username $password $src_file $dest_filedone

很简单的代码,指定了3个参数:列表文件的位置、本地源文件路径、远程主机目标文件路径。需要说明的是其中的列表文件指定了远程主机ip、用户名、密码,这些信息需要写成以下的格式:

IP username password

中间用空格或tab键来分隔,多台主机的信息需要写多行内容。

这样就指定了两台远程主机的信息。注意,如果远程主机密码中有“$”、“#”这类特殊字符的话,在编写列表文件时就需要在这些特殊字符前加上转义字符,否则expect在执行时会输入错误的密码。

对于这个shell脚本,保存为batch_scp.sh文件,与刚才保存的expect_scp文件和列表文件(就定义为hosts.list文件吧)放到同一目录下,执行时按照以下方式输入命令就可以了:

./batch_scp.sh ./hosts.list /root/src_file /root/destfile

===============================================================================

下面我们来看一些expect的一些内部参数:

exp_continue [-continue_timer]
             The command exp_continue allows expect itself to continue executing rather than returning as it  normally
             would.  By  default  exp_continue  resets the timeout timer. The -continue_timer flag prevents timer from
             being restarted.

exp_version [[-exit] version]
             is useful for assuring that the script is compatible with the current version of Expect.

With  no  arguments, the current version of Expect is returned.  This version may then be encoded in your
             script.  If you actually know that you are not using features of recent versions, you can specify an ear-
             lier version.

具体的用法还可以查看文档~

#!/bin/sh
# \
exec expect -- "$0" ${1+"$@"}
exp_version -exit 5.0
if {$argc!=2} {send_user "usage: remote-exec command password\n"send_user "Eg. remote-exec \"ssh user@host ls\; echo done\" password\n"send_user "or: remote-exec \"scp /local-file user@host:/remote-file\" password\n"send_user "or: remote-exec \"scp user@host:/remote-file local-file\" password\n"send_user "or: remote-exec \"rsync --rsh=ssh /local-file user@host:/remote-file\" password\n"send_user "Caution: command should be quoted.\n"exit
}
set cmd [lindex $argv 0]
set password [lindex $argv 1]
eval spawn $cmd
set timeout 600
while {1} {expect -re "Are you sure you want to continue connecting (yes/no)?" {# First connect, no public key in ~/.ssh/known_hostssend "yes\r"} -re "assword:" {# Already has public key in ~/.ssh/known_hostssend "$password\r"} -re "Permission denied, please try again." {# Password not correctexit} -re "kB/s|MB/s" {# User equivalence already established, no password is necessaryset timeout -1} -re "file list ..." {# rsync startedset timeout -1} -re "bind: Address already in use" {# For local or remote port forwardingset timeout -1} -re "Is a directory|No such file or directory" {exit} -re "Connection refused" {exit} timeout {exit} eof {exit}
}

注意用法:

Eg. remote-exec "ssh user@host ls; echo done" password
or: remote-exec "scp /local-file user@host:/remote-file" password
or: remote-exec "scp user@host:/remote-file local-file" password
or: remote-exec "rsync --rsh=ssh /local-file user@host:/remote-file" password
Caution: command should be quoted.

转自

expect学习笔记及实例详解 - 小菜鸟的天地 - 博客频道 - CSDN.NET
http://blog.csdn.net/zhuying_linux/article/details/6904568

转载于:https://www.cnblogs.com/paul8339/p/6699859.html

expect学习笔记及实例详解【转】相关推荐

  1. expect学习笔记及实例详解

    转载自: http://ifis.blog.hexun.com/44587020_d.html 1. expect是基于tcl演变而来的,所以很多语法和tcl类似,基本的语法如下所示: 1.1 首行加 ...

  2. ELK学习笔记之Logstash详解

    0x00 Logstash概述 官方介绍:Logstash is an open source data collection engine with real-time pipelining cap ...

  3. Java中大数据数组,Java基础学习笔记之数组详解

    摘要:这篇Java开发技术栏目下的"Java基础学习笔记之数组详解",介绍的技术点是"java基础学习笔记.基础学习笔记.Java基础.数组详解.学习笔记.Java&qu ...

  4. oracle scn 重置,学习笔记:Oracle SCN详解 SCN与Oracle数据库恢复的关系

    天萃荷净 分享一篇关于Oracle SCN的详解,介绍SCN与Oracle数据库恢复的关系和SCN在数据库中的作用 一.为什么需要System checkpoint SCN号与Datafile Che ...

  5. PyQt5学习笔记——一文详解QObject

    QObject详解笔记1 一.简介 QObject是所有Qt对象的基类 二.功能作用 2.1 对象名称.属性 2.1.1 API setObjectName("唯一名称") 给QT ...

  6. shell入门学习笔记-12-命令详解: echo与printf

    系列目录与参考文献传送门: shell入门学习笔记-序章 命令详解 admindeMacBook-Pro:myshell admin$ type cd cd is a shell builtin ad ...

  7. CoAP学习笔记——CoAP格式详解

    0 前言 CoAP是受限制的应用协议(Constrained Application Protocol)的代名词.在当前由PC机组成的世界,信息交换是通过TCP和应用层协议HTTP实现的.但是对于小型 ...

  8. Docker技术入门与实战 第二版-学习笔记-3-Dockerfile 指令详解

    前面已经讲解了FROM.RUN指令,还提及了COPY.ADD,接下来学习其他的指令 5.Dockerfile 指令详解 1> COPY 复制文件 格式: COPY  <源路径> .. ...

  9. PHP正则表达式笔记与实例详解

    链接:https://www.jb51.net/article/160947.htm 笔记: 一.正则表达式的介绍: 二. 语法: 三. 正则表达式的组成部分: 四. 正则表达式的函数: 实例: 1. ...

最新文章

  1. C#连接Oracle数据库的方法(Oracle.DataAccess.Client也叫ODP.net)
  2. 【原创】开源Math.NET基础数学类库使用(14)C#生成安全的随机数
  3. U盘拒绝访问怎么办 快速方法解决U盘问题
  4. Vlan与VTP的介绍及工作原理
  5. 孤读Paper——《ATSS:Adaptive Training Sample Selection》
  6. sitecore系统教程之使用修补程序文件自定义Sitecore配置
  7. linux7 yum安装Mysql5.7
  8. 数学建模算法与应用(目录)
  9. Lottie 动画AE+Bodymovin导出的JSON文件解读
  10. 爱尚QQ网修改QQ在线机型源码
  11. matlab宝典pdf,《MATLAB 宝典(第4版)》---- 优化.pdf
  12. 确定有限自动机DFA
  13. 《非暴力沟通》---第二章(是什么蒙蔽了爱?)读书笔记
  14. 百度地图常用jsapi
  15. XMap 简易的Java-xml映射工具类库
  16. python实现进制转换器_python实现各进制转换的总结大全
  17. 从左上角到右下角 棋盘问题_分治算法之棋盘问题
  18. 如何在mysql 中建立有关联关系的表
  19. 10Gb每秒!SM4的单核“心”!海泰携手海量数据安全“闪”护
  20. 设计模式之模板方法模式在kafka DelayedOperation中的应用

热门文章

  1. Fastdfs分布式文件系统的应用
  2. myEclipse 界面窗口打不开问题
  3. 【mongodb系统学习之三】进入mongodb shell
  4. FlashBuilder找不到所需要的AdobeFlashPlayer调试器版本的解决方案
  5. 软考倒计时7天:题目书中的易混点
  6. 查看oracle中各个表空间的已使用空间和最大分配空间
  7. React中JSX的理解
  8. bash 后台程序_如何向您的Bash程序添加帮助工具
  9. 销售面销五个最基础步骤步骤_3个步骤,可提供强有力的反馈
  10. TypeScript 之泛型