用Expect实现命令行交互的自动化操作
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 是一种可执行程序,从它正确地处理用 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
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
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