Autoexpect

翻译至:http://www.admin-magazine.com/Articles/Automating-with-Expect-Scripts

当然,有些懒的系统管理员懒到一个更高的水平,甚至在编写Expect script上造假,他们通过调用一个名为 Autoexpect 的脚本 “watcher” 或记录脚本来干这事 。 一旦被调用,Autoexpect 观察你的每一个按键,并记录到默认的名为 script.exp 的文件中。你几乎肯定是要编辑和修改这个脚本来实现你想要的结果; 但是,有一个几乎完全工作的脚本可以节省数小时的脚本调试时间。

如果你只是运行一个新创建的Autoexpect脚本,它很可能会失败,因为,如果你通过在在屏幕上显示信息的方式发出一个回答你请求的命令,脚本也会追加这个问题的回答,并把它复制到脚本文件中。

例如,如果在你的Autoexpect会话期间,你键入 ls,该命令的结果会显示在你的 script.exp 文件中。 在你已经手动创建过了一些 Expect 脚本之后,你会明白如何去清理Autoexpect创建的脚本,你必须要这么做。

要安装Autoexpect,使用这样的命令: 

$ sudo apt-get install expect-dev

你可能需要安装更多的依赖支持该功能,所以在一切安装完之前等一会儿。

通过Autoexpect创建一个交互式SSH会话

在安装完Autoexpect及其所有必需的包之后,你就可以通过执行你要自动运行的程序来自动创建Expect脚本。 使用上面的例子,SSH到远程系统并运行:

ps -ef |grep apache

命令然后注销。

调用Autoexpect很简单:

$ Autoexpect

Autoexpect started, file is script.exp
$

虽然看起来好像什么都没发生过,但你键入的每个按键将被记录到script.exp。 你收到的每个标准输出响应也将被复制到同一个文件。你的整个会话会被记录 - 但不仅仅是记录,同时还格式化成Expect风格的脚本。要停止录制按键到你的脚本,在键盘上按Ctrl + D停止 Autoexpect 并拷贝缓冲区到你的文件。

这个简单的程序的完整转录非常长,而且包括了作者 Don Libes 的许多注释:

#!/usr/bin/expect -f
#
# This Expect script was generated by Autoexpect on Thu Oct 11 15:53:18 2012
# Expect and Autoexpect were both written by Don Libes, NIST.
#
# Note that Autoexpect does not guarantee a working script.  It
# necessarily has to guess about certain things.  Two reasons a script
# might fail are:
#
# 1) timing - A surprising number of programs (rn, ksh, zsh, telnet,
# etc.) and devices discard or ignore keystrokes that arrive "too
# quickly" after prompts.  If you find your new script hanging up at
# one spot, try adding a short sleep just before the previous send.
# Setting "force_conservative" to 1 (see below) makes Expect do this
# automatically - pausing briefly before sending each character.  This
# pacifies every program I know of.  The -c flag makes the script do
# this in the first place.  The -C flag allows you to define a
# character to toggle this mode off and on.

set force_conservative 0  ;# set to 1 to force conservative mode even if
                          ;# script wasn’t run conservatively originally
if {$force_conservative} {
        set send_slow {1 .1}
        proc send {ignore arg} {
                sleep .1
                exp_send -s -- $arg
        }
}

#
# 2) differing output - Some programs produce different output each time
# they run.  The "date" command is an obvious example.  Another is
# ftp, if it produces throughput statistics at the end of a file
# transfer.  If this causes a problem, delete these patterns or replace
# them with wildcards.  An alternative is to use the -p flag (for
# "prompt") which makes Expect only look for the last line of output
# (i.e., the prompt).  The -P flag allows you to define a character to
# toggle this mode off and on.
#
# Read the man page for more info.
#
# -Don

set timeout -1
spawn $env(SHELL)
match_max 100000
expect -exact "]0;khess@trapper: ~khess@trapper:~\$ "
send -- "ssh aspen\r"
expect -exact "ssh aspen\r
khess@aspen’s password: "
send -- "PASSWORD\r"
expect -exact "\r
Linux aspen 2.6.32-43-server #97-Ubuntu SMP Wed Sep 5 16:56:41 UTC 2012 x86_64 GNU/Linux\r
Ubuntu 10.04.4 LTS\r
\r
Welcome to the Ubuntu Server!\r
 * Documentation:  http://www.ubuntu.com/server/doc\r
\r
  System information as of Thu Oct 11 15:55:28 CDT 2012\r
\r
  System load:  1.09               Temperature:         40 C\r
  Usage of /:   1.0% of 454.22GB   Processes:           168\r
  Memory usage: 22%                Users logged in:     1\r
  Swap usage:   0%                 IP address for eth0: 192.168.1.250\r
\r
  Graph this data and manage this system at https://landscape.canonical.com/\r
\r
7 packages can be updated.\r
7 updates are security updates.\r
\r
New release ‘precise’ available.\r
Run ‘do-release-upgrade’ to upgrade to it.\r
\r
*** System restart required ***\r
Last login: Thu Oct 11 15:53:41 2012 from trapper\r\r
]0;khess@aspen: ~khess@aspen:~\$ "
send -- "ps -ef|grep apache\r"
expect -exact "ps -ef|grep apache\r
www-data   555 23171  0 Oct07 ?        00:00:00 /usr/sbin/apache2 -k start\r
www-data   556 23171  0 Oct07 ?        00:00:00 /usr/sbin/apache2 -k start\r
www-data   557 23171  0 Oct07 ?        00:00:00 /usr/sbin/apache2 -k start\r
www-data   558 23171  0 Oct07 ?        00:00:00 /usr/sbin/apache2 -k start\r
www-data   559 23171  0 Oct07 ?        00:00:00 /usr/sbin/apache2 -k start\r
khess    21504 21433  0 15:55 pts/1    00:00:00 grep apache\r
root     23171     1  0 Sep27 ?        00:00:28 /usr/sbin/apache2 -k start\r
]0;khess@aspen: ~khess@aspen:~\$ "
send -- "exit\r"
expect -exact "exit\r
logout\r
Connection to aspen closed.\r\r
]0;khess@trapper: ~khess@trapper:~\$ "
send -- "^D"
expect eof
khess@trapper:~$

The parts you needed for this script to execute correctly are shown below in my cleaned up version.

你可以看到,在提炼这份转录到它的基本部分之前你有很多的清理工作为做。 Autoexpect也改变了script.exp 文件的权限,让它是可执行的。

您需要这个脚本能够正确执行的部分如下所示,这是我清理的版本。


#!/usr/bin/expect -f

set force_conservative 0  ;# set to 1 to force conservative mode even if
                          ;# script wasn’t run conservatively originally
if {$force_conservative} {
        set send_slow {1 .1}
        proc send {ignore arg} {
                sleep .1
                exp_send -s -- $arg
        }
}

set timeout -1
spawn $env(SHELL)
match_max 100000
expect -exact "$ "
send -- "ssh aspen\r"
expect -exact "password: "
send -- "PASSWORD\r"
expect -exact "$ "
send -- "ps -ef|grep apache\r"
expect -exact "$ "
send -- "exit\r"
expect -exact "$ "

可以看到,复杂的提示,如

expect -exact "exit\r
logout\r
Connection to aspen closed.\r\r
]0;khess@trapper: ~khess@trapper:~\$ "

已显著缩短为:

expect -exact "$ "

提示仍然有效,因为 Expect 寻找在 expect 行的最后几个字符,而不是整个字符串。你可以缩短密码预期的提示行从:

expect -exact "password: "

expect -exact ": "

注意如果缩短你的 expect 行太多的话 - 这会使脚本更加困难,不容易读,以及在将来当您试图弄清楚这是怎么回事时很难解析。 你可能不知道“:”是一个密码提示。 除非你足够聪明在你的脚本中包括注释,你可能会花几个小时的调试这个缩短的版本。 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值