目录
[在shell 中嵌套expect](#在shell 中嵌套expect)
[Shell Here Document(内嵌文档/嵌入文档)](#Shell Here Document(内嵌文档/嵌入文档))
[Here Document 的基本用法](#Here Document 的基本用法)
❀ expect 命令运用于 bash ❀
功能说明: expect是一款自动化的脚本解释型的工具。
(ps.expect基于tcl脚本,expect脚本的运行需要tcl的支持。expect对一些需要交互输入的命令很有帮助,比如ssh ftp scp telnet。远程登录linux服务器的时候**** ,ssh命令需要手工输入密码,当登录多台机器的时候就会非常繁琐。expect就可以根据设定的规则,自动帮我们输入密码,大大节省了时间。在shell脚本中使用expect命令可以实现自动化交互式操作,例如自动登录远程服务器、自动执行命令等。)
expect使用原理
spawn启动指定进程---expect获取指定关键字---send向指定程序发送指定字符---执行完成退出。
expet使用场景
①并根据预定标准回答其问题,回答"是"、"否"或将控制权交还给您
②**远程连接设备并执行自动化操作**
③主要是一些需要人机交互的地方,如果提前知道应该输入什么指令都可以使用expect 工具
常用的expect命令选项
spawn :启动一个新的进程,并将其与当前进程进行交互。
expect:等待特定的字符串或正则表达式出现,并执行相应的操作。
send :向进程发送字符串,并将该参数发送到进程,这个过程类似模拟人类输入密码。
interact :允许用户与进程进行交互,interact命令可以在适当的时候进行任务的干预,比如下载完ftp文件时,仍然可以停留在ftp命令行状态,以便手动的执行后续命令。
exp_continue :允许expect继续向下执行指令,在expect中多次匹配就需要用到。
exit :退出expect脚本。
eof :expect执行结束,退出。
set :设置变量。
puts :输出变量。
Timeout :指定超时时间 ,set timeout n,过期则继续执行后续指令 ,设置超时时间,表示该脚本代码需在n秒钟内完成,如果超过,则退出。timeout -1 为永不超时, 用来防止ssh远程主机网络不可达时卡住及在远程主机执行命令宕住。默认情况下,timeout是10秒。
send_user :回显命令,相当于echo。
$argv参数数组 :Expect脚本可以接受从bash传递的参数 ,可以使用****[lindex $argc n]****获得,n从0开始,分别表示第一个,第二个,第三个...参数。
(arg :参数 ; v :value。)
Expect脚本的结尾
expect脚本必须以interact 或expect eof结束,执行自动化任务通常expect eof就够了
expect eof是在等待结束标志。由spawn启动的命令在结束时会产生一个eof标记,expect eof就是在等待这个标记。
常用的expect命令选参数
-c :命令行执行expect脚本
-i :交互地执行expect脚本。使用"-i"选项,可以通过来自于标准输入的读命令来交互地执行expect脚本。
-d :debug模式,可以在运行时输出一些诊断信息,输出调试信息 。 示例:expect -d ssh.exp
-D:启用交换调式器,可设一整数参数
-f 从文件读取命令,仅用于使用#!时。如果文件名为"-",则从stdin读取(使用"./-"从文件名为-的文件读取)
-v 显示expect版本信息
-b:不解释命令行参数
Expect执行方式
单一分支语法
expect "password:" {send "mypassword\r"}
多分支模式语法第一种
expect "aaa" {send "AAA\r"}
expect "bbb" {send "BBB\r"}
expect "ccc" {send "CCC\r"}
ps.send命令不具备回车换行 功能,所以需要自己添加**\r** 或 \n
多分支模式语法第二种
expect {
"aaa" {send "AAA\r"}
"bbb" {send "BBB\r"}
"ccc" {send "CCC\r"}
}
#只要匹配了aaa 或bbb或ccc中的任何一个,执行相应的send语句后就会退出该expect语句
expect {
"aaa" {send "AAA\r";exp_continue}
"bbb" {send "BBB\r";exp_continue}
"ccc" {send "CCC\r"}
}
#exp_continue 表示继续后面的匹配 ,如果匹配了aaa,执行完send语句后还会继续向下匹配bbb
#捕捉内容要用双引号引起来
#send要写在****{}**** 中,输出信息也要用双引号 引起来,分号"; "要写在****}****里面。
在shell 中嵌套expect
bash
#!/bin/bash
user=root
ip=192.168.56.103
passwd='123456'
expect <<-EOF
set time 30
spawn ssh $user@$ip
expect {
"*yes/no" { send "yes\n"; exp_continue }
"*password" { send "$passwd\n" }
}
interact
EOF
其中 <<-EOF 和 EOF 包围的内容块,被重定向到左侧命令expect 的 stdin 中。
Shell Here Document(内嵌文档/嵌入文档)
Shell 还有一种特殊形式的重定向叫做"Here Document",目前没有统一的翻译,你可以将它理解为"嵌入文档""内嵌文档""立即文档"。
所谓文档,就是命令需要处理的数据或者字符串;所谓嵌入,就是把数据和代码放在一起,而不是分开存放(比如将数据放在一个单独的文件中)。有时候命令需要处理的数据量很小,将它放在一个单独的文件中有点"大动干戈",不如直接放在代码中来得方便。
Here Document 的基本用法
command <<EOF
document
EOF
command是 Shell 命令,<<EOF 是开始标志,EOF是结束标志,document是输入的文档(也就是一行一行的字符串)。
这种写法告诉 Shell 把 document 部分作为命令需要处理的数据,直到遇见终止符EOF为止(终止符EOF不会被读取)。
注意,终止符EOF必须独占一行,并且要定顶格写。
分界符(终止符)可以是任意的字符串,由用户自己定义,比如 END、MARKER等,ABC也可以,只要前后一致,分界符可以出现在正常的数据流中,只要它不是顶格写的独立的一行,就不会被作为结束标志。
结尾的标记一定要顶格写,前面不能有任何字符,除了空格, 结尾的标记后面也不能有任何字符(包括空格)
用法说明
Expect是一种将现有的实用程序组合起来的胶合剂,通常考虑的是如何使Expect利用系统现有的工具解决问题而不是如何在Expect中解决问题。
Expect主要应用涉及商用软件产品。很多这类的产品都会提供某种命令行工具,但这些工具缺乏脚本编程的能力,只是为了帮助用户管理产品,而商家通常不会在如何实现一个稳定性好的脚本语言上耗费很多精力。Expect脚本中可以包含shell,查询环境变量,通过执行某些Unix命令获得更多的信息,然后在产品所带命令行接口中加入必须的信息,来完成用户的目标。在产品命令行接口中查询相关信息,该脚本可以在多种选择中智能地决定当前应该做什么比较合适。
每次Expect 操作完成,运行结果将保存在本地环境变量 $expect_out 中。这允许脚本收集这些信息给用户以相应的反馈,同时也允许根据当前情况发送相对应的指令。
Expect通常用来建立一组测试套件,可以用在程序、组件或者嵌入式系统中。DejaGnu就是利用Expect写成的一组测试套件。它被大量地应用于测试 gcc,对于远程目标的测试例如嵌入式开发也是非常合适的。
你可以利用一种叫作"autoexpect"的工具,自动生成expect脚本。这个工具观测你的操作,并利用启发性知识生成expect脚本。尽管生成的代码可能会很长,含义上有点模糊,你可以修改生成的脚本使它成为你需要的代码。
观点
利
Expect可通过cron封装系统管理任务,在规定的时期运行。能够这样做是因为Expect仅仅使用已经安装在主机中的系统管理工具,不需要学习额外的工具。如果程序员学过Tcl,那么转移到Expect是一件非常简单的工作,相同的编程结构和语法,再加上一些内置的额外功能。
业界对室内管理任务使用Expect提供了很大的支持。Expect在很多的公司广泛使用,例如Silicon Graphics, IBM, HP, Sun, Xerox, Amdahl, Tektronix, at&T, ComputerVision和世界银行,利用Expect对开发项目、文件传输、帐号管理、网络测试进行室内自动测试。
Expect已经以多种模块的方式移植到Python和perl语言中。Expect命令的部分子集移植到Java和嵌入到SwichTermJ(基于Java的终端仿真器)之中。这些例行程序通常是原程序的同等功能的另一种解释方式。一旦你理解了其中的概念,如果需要的话,换到其它语言,也就很容易了。
弊
Expect继承了Tcl的语法规范,对于使用其它脚本语言的人来说这是相当陌生的。和其它语言如bash、csh和Perl相比,Expect的语法模式是不同的。就像有时候一个变量的前缀冠以"$",有时候又不需要。有些版本的Expect和Perl、Python语言的语法倒是很相似的。
另一个缺陷是在不同的平台移植Expect脚本很难。例如,一个Expect脚本使用基于Unix的工具,就不可能适合移植到Windows平台。如果可能的话,程序员必须找到相应的命令行程序,能够提供相同的信息,这就可能需要修改expect脚本的send部分,而这部分恰恰就是整个脚本的核心。如果你使用的是tcl,perl或者python这些独立于平台的工具,使用它们各自的POSIX接口访问文件、对远端交互进行标准的POSIX处理(telnet,ftp等等),就不会出现上述问题。
一个不明显的缺陷是,有时Expect可能并不是解决问题的最好方法。例如,一个系统管理员需要登录到多个服务器,这些自动的操作要使用Expect就得配以保存的密码,而不是更安全的解决方案采用ssh代理密钥。虽然这种自动交互工具很吸引人,但是还是有很多其它的办法可以更安全稳定地解决同样的问题。
Expect自动化控制命令行工具,但是对图形用户界面就失效了。Windows提供了不少有价值的工具,很多是基于图形用户界面的,这就是Expect失效的地方了。Windows下图形界面程序可以通过像Autohotkey或者AutoIt等工具来实现自动化控制。