| Subcribe via RSS

用Expect实现命令行交互的自动化操作

7月 11th, 2008 | 1 Comment | Posted in shell < by Martian Guo >

Expect 是一个控制交互式程序的工具。你可以用它来编写一段脚本来处理一些交互式的操作,比如执行passwd、su 远程登录 ssh,远程命令操作等 ,如果你有多台服务器需要执行相同的操作命令,用Expect就比较适合。
下面这段文字描述了expect的一些概念。

* Expect 是一种特定的、高级的和通用的编程语言,其语法与 Tcl 相同,并增加了 Tcl 中所没有的一些特殊用途的命令。
    * Expect 是一种可执行程序,从它正确地处理用 Expect 语言编写的输入的角度来看,它实现了这种语言。
    * expect 命令是其中的一个命令,Expect 以此对 Tcl 进行了扩展。
    * Expect 是一个 Tcl 包。一般说来,这意味着任何 Tcl 应用程序都可以在运行时加载 Expect 功能。
    * Expect 是一个基于 C 源代码的库,而这些 C 源代码则深入到 Expect 可加载的包和 Expect 可执行程序。
    * Expect 是某种工具的抽象概念,该工具:
          o 实现终端交互的自动化,甚至在涉及到密码或者其他特殊项目的情况下
          o 实现了一种“对话”模型,通过它对消息和响应的简单规律进行编码

下面两篇文章详细介绍了Expect的使用
http://fanqiang.chinaunix.net/a4/b8/20010912/1000001278.html
http://www.ibm.com/developerworks/cn/aix/library/au-expect/index.html

当然,在学习Expect 之前你应当先学习一些Tcl编程的内容,请看这里 TclTk中文网,另外expect 的安装需要依赖Tcl,你必须首先安装 Tcl。

下面是我写的一段演示脚本,主要操作是从一个文本中批量读取ip地址,普通用户用户名和密码,超级用户密码,执行ssh登录,su root 操作 然后退出

pwd.txt

127.0.0.1       mars    1234        root            123456
192.168.0.3       mars    1234        root            123456

run.exp

#!/usr/bin/expect
set timeout 5
proc do_ssh_login {host username pass susername spass} {
    
set timeout_case 0
    
set done 1
 
    
send_user "\n"
    
spawn ssh $username@$host
    
send_user "正在连接主机 $host\n"
    
while {$done} {
 
    
expect {
            
timeout {
                  
switch -- $timeout_case {
                
0 { send "\n" }
                
1 {
                      
send_user "重试...\n"
                      
send "\n"
                  
}
                
2 {
                    
puts stderr "登录超时...\n"
            
close
            
set done 0
            
break
                  
}
              
}
              
incr timeout_case
              
}
 
        
"*(yes/no)?" {send "yes\n"}       
        
"?assword:"  {send "$pass\n"}
        
"*Permission denied*" {    send_user "登录受限\n"
                    
close
                    
set done 0
                    
break
                      
}
          
"*Connection refused*" { send_user "主机不可访问\n"
                    
close
                    
set done 0
                    
break
                      
}
        
"*$*" {send_user "\n登录成功...\n"
            
if {[string  equal $susername "NULL"] !=1} {
                    
send "export LC_ALL=en_US\r"
                    
send "su - $susername\r"
                      
expect "*Password:*"
                      
sleep 1
                      
send "$spass\n"
                
expect {
                    
"*Authentication failure*" {send_user "密码错误\n"
                                        
close
                                    
break
                                          
}
                          
"*Permission denied*" {send_user "登录受限\n"
                                      
close
                                  
break
                                          
}   
                        
}
            
}
              
}
        
"*#*" {
                
send_user  "超级用户登录成功\n"
                
send_user "\n*************************$host********************************\n"
                
send "cat /proc/cpuinfo |grep model\\ name\n"
                
expect "#"
                
send "df -T\n"
                
expect "#"
                
send "fdisk -l\n"
                
expect "#"
                
send "free\n"
                
expect "#"
                
send "lspci\n"
                
expect "#"
                
expect {
                
"#" {set done 0
                    
send_user "\n***************************************************************\n"
                    
send_user "\n"
                    
send "exit\n"
                  
}
                
}
          
}
        
}
    
}
 
}
 
set f [open "pwd.txt" r]
while { [gets $f line] >= 0 } {
set su [lindex $line 3]
set sp [lindex $line 4]
if { [string length $su] <=0 } {
    
set sp "NULL"
    
set su "NULL"
}
do_ssh_login [lindex $line 0] [lindex $line 1] [lindex $line 2]  $su $sp
}
 
close $f
阅读内文 Tags: , , ,