Chinaunix首页 | 论坛 | 博客
  • 博客访问: 107967
  • 博文数量: 54
  • 博客积分: 1548
  • 博客等级: 上尉
  • 技术积分: 620
  • 用 户 组: 普通用户
  • 注册时间: 2008-11-06 00:37
文章分类

全部博文(54)

文章存档

2011年(1)

2010年(22)

2009年(31)

分类: 系统运维

2009-04-27 11:02:58

expect 是进行高效的系统和网络管理工作是不可或缺,实现自动交互的一种工具.
1.
#!/usr/bin/expect -f
-f   参数指定从哪个文件中读取命令。当被用在#!指示(见上)中时此参数是可选的,
     所以其它参数可在命令行中提供.
 
-i  参数使expect交互地提示输入命令,而不是从文件中读命令。命令提示行通过exit命令或一个eof字符
    结束。

cmd arg arg arg  : 一条Tcl命令由空格分割的单词组成. 其中, 第一个单词是命令名称, 其余的是命令参数 .
$foo        :     $符号代表变量的值. 在本例中, 变量名称是foo. 
[cmd arg]    :  方括号执行了一个嵌套命令. 例如, 如果你想传递一个命令的结果作为另外一个命令的参数, 那么你使用这个符号 .      
 "some stuff"  : 双引号把词组标记为命令的一个参数. "$"符号和方括号在双引号内仍被解释 .                
 {some stuff}  :  大括号也把词组标记为命令的一个参数. 但是, 其他符号在大括号内不被解释.
 斜线符号() 是用来引用特殊符号. 例如:n 代表换行. 反斜线符号也被用来关闭"$"符号 , 引号,方括号和大括号的特殊含义 .
   
可以通过-d参数调试Expect脚本: # /usr/bin/expect -d sample_login.exp user passwd
             
2.         
expect <set timeout 3600
spawn strace -o /dev/null ssh
EOF
expect的timeout时间, timeout是以秒为单位, 如果设置为0, 是根本就不等待, 设置为-1, 是永远等待.
spawn: 运行你需要交互的程序,后面跟上命令名和命令参数
expect {
    "yes/no" { send "yes/r";exp_continue }
 "password:" {send "$password\r"}
 }
send    向进程发送字符串。
expect  等待进程的某些字符串。
expect $prompt
脚本中的exp_continue命令的作用是用来继续expect . 如果在脚本中没有这个命令,
当输入完成“yes”后,expect已经返回,它会“expect $prompt”,它就没有机会输入密码。
在expect中调用了exp_continue相当于让脚本的又重新从expect处开始运行,有点类似于while或者for循环。
只是在这里没有判断条件。因此,在刚开始写expect脚本的时候,很容易就出现了死循环。----相当于shell,c中的continue。
3.
 spawn command  命令调用,激活一个Unix程序来进行交互式的运行。
嵌套命令
set LOGIN [ lindex $argv 0 ]
set PASS  [ lindex $argv 1 ]
一个Tcl函数lindex来实现的,该函数从列表/数组得到一个特定的元素。
[ ]用来实现将函数lindex的返回值作为set命令的参数。
命令行参数:$argc,$argv 0,$argv 1 ... $argv n
$argc 是指脚本在命令行有几个参数。
 
4.顺序和循环
if { } {
  exit 1 |0
}
for语句的格式有点类似这样:
for { set i 0} {$i < 10} { incr i} {puts $i}
case $variable {
  $var1 { }
  $var2 { }
  $var3 { }
}
while ( ){
}
5.运算
incr 增加
6.函数定义和调用
proc function_name { $argv } {
....
}
在proc里面直接return(后面没有带参数), 那么proc将会直接返回, 不会返回任何值.
否则, 将会返回最后一条语句的执行结果的返回值.
exit在任意的地方都能够退出tclsh的执行程序, 返回到shell.
例子:
proc do_console_login {login pass} {
   set timeout 5
   set done 1
   set timeout_case 0
   while ($done) {
   expect {
   "console login:" { send "$login\n" }
   "Password:" { send "$pass\n" }
   "#" {
   set done 0
   send_user "\n\nLogin Successfully...\n\n"
   }
   timeout {
   switch -- $timeout_case {
   0 { send "\n" }
   1 {
   send_user "Send a return...\n"
   send "\n"
   }
   2 {
   puts stderr "Login time out...\n"
   exit 1
   }
   }
   incr timeout_case
   }
   }
   }
  }
  proc do_exec_cmd {} {
   set timeout 5
   send "\n"
   expect "#"
   send "uname -p\n"
   expect "#"
   send "ifconfig -a\n"
   expect "#"
   send "exit\n"
   expect "login:"
   send_user "\n\nFinished...\n\n"
  }
  if {$argc<2} {
   puts stderr "Usage: $argv0 login passwaord.\n "
   exit 1
  }
  set LOGIN [lindex $argv 0]
  set PASS [lindex $argv 1]
  spawn telnet 10.13.32.30 7001
  do_console_login $LOGIN $PASS
  do_exec_cmd
  close
  exit 0
7. expect的default 相当于匹配了timeout和eof
8. expect的spawn了一个process, 如果结束了, 它会返回给expect一个eof信号,
   反过来, expect也可以主动来关闭spawn的process, 这时候,process也会看到一个eof信号,
   一般来说, process收到这个信号后, 它会主动关闭它自己.
9. 使用expect的re来匹配正则表达式, 那使用什么来表示glob匹配呢? 默认的就是使用glob来匹配,
    也可以使用显式的-gl来声明使用glob.假如要匹配一些expect的关键字,
   例如eof, default, timeout等, 就可以使用-re或者-gl来表示.
   如果在使用glob的时候, 如果匹配的pattern里面有变量,
   最好加上-gl, 防止由于变量的值为expect的关键字或者标志.
 
expect -re "\[(.*)]:"
if {$expect_out(1,string)!="/bin/tcsh"} {
send "/bin/tcsh" }
send " "
expect eof
1.)第一个expect命令现在使用了-re参数,这个参数表示指定的的字符串是一个正则表达式,而不是一个普通的字符串。
2.) 在一个正则表达时中,可以在()中包含若干个部分并通过expect_out数组访问它们。
   各个部分在表达式中从左到右进行编码,从1开始(0包含有整个匹配输出)。
3.) 当发现一个匹配则检查包含在[]中的字符串,查看是否为/bin/tcsh .
4.)在进行expect匹配的时候, 使用-nocase参数, nocase是将字符串转换成小写来进行匹配.
 
10
#!/usr/bin/expect -f
set timeout 10
expect " " {
set raw $expect_out(buffer)
# remove final carriage return
set response [string trimright "$raw" " "]
}   
expect命令就等待输出中出现回车字符。如果在超时之前得到回车符,
那么set命令就会将用户输入的内容赋值给变脸raw。
随后的命令将用户输入内容最后的回车符号去除以后赋值给变量response。
 
11. 输入和输出
输入:send
输出:puts stderr | stdout "   \n" | puts " "
expect_user 从标准输入读取数据.
expect_tty和expect_user的区别, expect_user能够被shell所重定向.
而expect_tty则是永远指从键盘读取输入. send_tty和send_user的 情况类似.

12.字符串应该用引号括起来:
% set str "test"
'test'
要输出一个标量的内容,使用put语句:
% puts $str
test
$用来说明str是一个变量。puts函数在标准输出显示变量的内容。
13. sleep是expect的一个标准命令,表示暂停若干秒钟。
    break , continue
#!/usr/bin/expect 
spawn ftp
while {1} {
expect "ftp>"
send "ip_address\r"
expect {
"Connected" break
"refused" { sleep 10} ;
}
}
14.一个简单实用例子脚本
#!/usr/bin/expect
foreach IP {
192.168.0.2
192.168.0.3
.............
} {
#循环,可以多台相同密码的服务器同时处理
spawn strace -o /dev/null ssh
#strace 信号追踪,直到命令执行完成,信号才会结束.避免一时连接不上,反复使用SSH连接.
expect {
"*(yes/no)*" { send "yes\r"}
"password:" { send "123456\r" }
}            #SSH第一次远程登录服务器
expect "username"
send "su -\r"        #SSH普通用户名密码登录
expect "Password:"
send "123456\r"        #SSH的root用户名密码登录
expect -timeout 1
expect "root"
send "route add -net 10.1.1.0 netmask 255.255.255.0 gw 10.1.1.1\r"
}
#expect -timeout sec 表示以后的对话,在sec秒完成后自动退出.
#route add  添加一条路由
#一般退出expect脚本:send "quit\r" 或者send "exit\r" 
阅读(1830) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~