n
p
1
1
EOF
(内容)
EOF
说明 <<EOF 的意思是 EOF 以后的内容,作为流输入 传给前面的应用, 直到遇到EOF ,中止输入.. 注意 EOF 前面不能有空格
Expect 和 Expect::Simple 都可以从 CPAN 网站上直接下载,最新版本为 Expect-1.21 和 Expect::Simple-0.04。比较方便的安装方法是使用 Perl 自带的包管理工具 cpan:
Expect 与最初的 Expect 语言类似,Expect 模块的主要功能也通过 spawn,expect,send 三个方法实现。 spawn:启动目标程序
spawn 是 Expect 类的主要方法之一,通过 fork 和 exec 启动目标程序,若成功则返回 Expect 对象,否则返回 undef。参数 $command 指定目标程序,@parameters 为可选参数。下面是一个简单的例子:
上述两行执行结果相同,但其实际处理过程存在细微差别。一般情况下我们可以把完整的命令行 ( 甚至可以是复合命令,包括命令、参数、管道符、重定向符等 ) 都写入 $command 而不指定 @parameters。 注:在 spawn 的实现中,$command 和 @parameters 都原封不动地传递给了 Perl 的 exec 函数。根据 exec 函数的说明文档,如果传递进来的是多元列表参数,exec 直接将其传递给 execvp 系统调用;如果传递进来的是标量参数或者单元列表参数,exec 函数将检查是否存在 shell 元字符 ( 如 | & ; ( ) < > 等 ),若存在,则将此参数交给系统 shell 进行解析,否则将其分词后传递给 execvp 系统调用。因此如果 spawn 的是一个含有 shell 元字符的复合命令,我们一般只能将其完整写入 $command。 expect:等待特定输出
使用 Expect 对象的 expect 方法等待目标程序的特定输出。参数列表中 $timeout 设定超时 ( 以秒为单位 ),@match_patterns 提供一个或多个匹配模式,如果在设定时间内目标程序输出结果和 @match_patterns 中某元素匹配则成功返回。缺省情况下 expect 使用精确匹配,若想使用正则表达式,可以在该模式元素前加 '-re' 前缀 :
标量上下文中 expect 返回匹配模式在 @match_patterns 中的位置 ( 注意下标从 1 开始 ),若不成功则返回 undef。而列表上下文中 expect 返回一个包含详细匹配信息的列表:
其中 $pos 就是在标量环境中的返回值,$err 是出错信息,$match 为成功匹配的字串,$before 为匹配字串之前的输出部分,$after 为匹配字串之后的输出部分。 send:发送数据
当交互式程序等待用户输入时,可以使用 send 方法向其提供输入数据。需要注意,send 送出的数据可能会回显在终端上 ( 具体与终端设置有关 ),此数据会进入 Expect 对象的匹配缓冲区,被下一个 expect 动作接收。为了避免 send 数据对 expect 匹配造成混乱,一般可以使用 |
$exp
= new Expect;
#new一个Expect.
$exp
->spawn(
$command
,
@params
);
#fork和exec一个新进程用来执行$command命令.
$exp
->expect(
$timeout
,
$content
);
#'-re'.在$timeout内,期待出现包含$content内容的正则表达式,如果不加re默认是精确匹配,也可以使用正则表达式,expect($timeout,re=>'').
$exp
->
send
(
$string
);
#向终端发送字符
$exp
->debug(0|1|2);
#打印debug 信息,不同的数字表示不同的bug级别
$exp
->interact();
#和用户进行交互,把控制权转交给用户
$exp
->soft_close();
#软关闭,直到$timeout时间到达,才关掉该进程
$exp
->hard_close();
#硬关闭,立刻关闭该进程
$exp
->match();
#返回匹配的结果
$exp
->match_number();
#返回匹配的个数
$exp
->send_slow();
# 就是让command慢慢敲进去..
$exp
->stty();
#它和外部命令 stty 类似,设定 terminal 的模式,-raw 还是 -cooked.开关回显 echo 和 -echo.
$ vi fdisk.exp
Shell代码
1.
2.
3.
4.
5.
6.
7.
8.
$ chmod +x fdisk.exp
$ ./fdisk.exp ## 输出如下
Shell代码
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.Command
11.
12.Disk
13.255
14.Units
15.
16.
17./dev/hda1
18./dev/hda2
19./dev/hda3
20./dev/hda5
21./dev/hda6
22./dev/hda7
23./dev/hda8
24./dev/hda9
25.
#!/usr/bin/expect
set SIZE ""
set date [exec date "+%Y-%m-%d"]
set DEV [exec fdisk -l | grep "Disk /dev/*" | cut -c 6-13 | grep -v "a" ]
puts "$DEV"
spawn fdisk $DEV
expect "Command (m for help):"
exec sleep 0.5
send "n\r"
expect "*"
send "p\r"
expect "(1-4):"
send "1\r"
expect "default 1):"
send "\r"
expect "*):"
send "\r"
expect "Command (m for help):"
send "w\r"
interact
使用expect实现自动登录的脚本,网上有很多,可是都没有一个明白的说明,初学者一般都是照抄、收藏。可是为什么要这么写却不知其然。本文用一个最短的例子说明脚本的原理。
脚本代码如下:
1 2 3 4 5 6 7 8 | ############################################## #!/usr/bin/expect set timeout 30 spawn ssh -l username 192.168.1.1 expect "password:" send "ispassr" interact ############################################## |