expect是构建在tcl基础上的一个工具,它拿来让一些须要交互的任务手动化地完成。
由于expect是基于tcl的linux设置环境变量,所以须要你的系统中安装有tcl
用法1.[#!/usr/bin/expect]
这一行告诉操作系统里的代码使用那一个来执行。这儿的expect似乎和linux下的bash、windows下的cmd是一类东西。
***注意:这一行须要在的第一行。
2.[settimeout30]
设置超时时间,计时单位:秒。timeout-1为永不超时,默认情况下,timeout是10秒。
3.[spawnssh-lusername192.168.1.1]
spawn是步入expect环境后才可以执行的expect内部,假如没有装expect或则直接在默认的SHELL下执行是找不到spawn的。所以不要用“whichspawn“之类的去找spawn命令。
主要功能是拿来开始一个新的进程。
spawn前面加上须要执行的shell命令,例如说spawnsudotouchtestfile.
4.[expect“password:”]
这儿的expect也是expect的一个内部命令,功能是判定先前输出结果里是否包含“password:”的字符串,假如有则立刻返回,否则就等待一段时间后返回,这儿等待时长通过settimeout来设置。
5.[send“ispassr”]
这儿就是执行交互动作,与手工输入密码的动作等效。
***温情提示:命令字符串结尾别忘掉加上“r”,倘若出现异常等待的状态可以核查一下。
6.[interact]
执行完成后保持交互状态,把控制权交给控制台,这个时侯就可以手工操作了。假如没有这一句登陆完成后会退出,而不是留在远程终端上。
7.[expecteof]
与spawn对应,表示捕捉终端输出信息中止,结束交互。
8.send和send_user
send会将expect脚本中须要的信息发送给spawn启动的哪个进程,而send_user只是回显用户发出的信息,类似于shell中的echo而已。
9.exp_continue的用法
使用exp_continue后,会重新从当前expect块的开始重新执行,可以简单理解为while循环的continue.
expect {
-re "Permission denied, please try again." {
send_user "Error:Permission denied.n"
exit
}
-re "Are you sure you want to continue connecting (yes/no)?" {
send "yesr";exp_continue
}
-re "assword:" {
send "$loginpassr";exp_continue
}
-re "Connection refused" {
exit
}
timeout {
exit
}
eof {
exit
}
}
事例#1
下边的脚本事例,实现了:登陆一个Linux服务器,执行df-h等命令。
viexpectExample.sh后输入下边的脚本内容保存后,使用chmod+xexpectExample.sh命令为脚本赋于可执行权限。
#!/usr/bin/expect -f
#--- set the variable,you can modify the value
set ipaddr [lrange $argv 0 0]
set port [lrange $argv 1 1]
set loginuser [lrange $argv 2 2]
set loginpass [lrange $argv 3 3]
set cmd_prompt "]#|~]?"
#超时时间,单位(秒)
set timeout 3600
#--- login by ssh
spawn ssh -p $port $loginuser@$ipaddr
expect {
-re "Permission denied, please try again." {
send_user "Error:Permission denied.n"
exit
}
-re "Connection refused" {
send_user "Error:Connection refused.n"
exit
}
timeout {
exit
}
eof {
exit
}
-re "Are you sure you want to continue connecting (yes/no)?" {
send "yesr"
exp_continue
}
-re "assword:" {
send "$loginpassr"
exp_continue
}
-re $cmd_prompt {
send "r"
}
}
#--- now,we do some commands
expect {
-re $cmd_prompt {
send "df -hr"
}
}
expect {
-re $cmd_prompt {
send "free -mr"
}
}
expect {
-re $cmd_prompt {
send "uptimer"
}
}
send "cd /optr"
send "mkdir shanhy123r"
send "cd shanhy123r"
send "echo 123 > 123.txtr"
send "/opt/xs.shr"
send "exitr"
expect eof
#interact
其中xs.sh为一个shell脚本,上面做了一个sleep模拟历时操作,代码如下:
#!/bin/bash
sleep 10
echo abc > /opt/abc.txt
#2
#!/usr/bin/expect
set passwd "mypasswd"
set timeout 60
if {$argc != 1} {
send "usage ./account.sh $newaccountn"
exit
}
set user [lindex $argv [expr $argc-1]]
spawn sudo useradd -s /bin/bash -g mygroup -m $user
expect {
"assword" {
send_user "sudo nown"
send "$passwdn"
exp_continue
}
eof
{
send_user "eofn"
}
}
spawn sudo passwd $user
expect {
"assword" {
send "$passwdn"
exp_continue
}
eof
{
send_user "eof"
}
}
spawn sudo smbpasswd -a $user
expect {
"assword" {
send "$passwdn"
exp_continue
}
eof
{
send_user "eof"
}
}
第3行:对变量形参的技巧;
第4行:默认情况下,timeout是10秒;
第6行:参数的数量可以用argc得到;第11行:参数存在argc得到;第11行:参数存在argc得到;第11行:参数存在argv当中,例如取第一个参数就是[lindex$argv0];而且假如须要估算的话必须用exprlinux set命令例子,如估算2-1,则必须用[expr2-1];
第13行:用spawn来执行一条shell命令,shell命令依照具体情况可自行调整;有文章说sudo要加-S,经过实际测试,无需加-S亦可;
第15行:通常情况下,假如连续做两个expect,这么实际上是串行执行的,用事例中的结构则是并行执行的,主要是看匹配到了哪一个;在这个事例中,假如你写成串行的话,即
expect "assword"
send "$passwdn"
expect eof
send_user "eof"
这么第一次将会正确运行,由于第一次sudo时须要密码;并且第二次运行时因为密码早已输过(默认情况下sudo密码再度输入时间为5分钟),则不会提示用户去输入,所以第一个expect将未能匹配到assword,但是必须注意的是假如是spawn命令出现交互式提问的并且expect匹配不上的话,这么程序会根据timeout的设置进行等待;而且假如spawn直接发出了eof也就是本例的情况,这么expect"assword"将不会等待,而直接去执行expecteof。这时都会报expect:spawnidexp6notopen,由于没有spawn在执行,旁边的expect脚本也将会由于这个缘由而不再执行;所以对于类似sudo这些命令分支不定的情况,最好是使用并行的形式进行处理;
第17行:仅仅是一个用户提示而已,可以删掉;
第18行:向spawn进程发送password;
第19行:促使spawn进程在匹配到一个后再去匹配接出来的交互提示;
第21行:eof是必须去匹配的,在spawn进程结束后会向expect发送eof;倘若不去匹配,有时也能运行,例如sleep多少秒后再去spawn下一个命令,并且不要依赖这些行为,很有可能明天还可以,今天就不能用了;
#3
下边这个事例比较特殊,在整个过程中就不能expecteof了:
#!/usr/bin/expect
set timeout 30
spawn ssh 10.192.224.224
expect "password:"
send "mypasswordn"
expect "*$"
send "mkdir tmpdirn"
expect "*$"
timeout指expect等待命令至多等30seconds
这个事例实际上是通过ssh去登陆远程机器,但是在远程机器上创佳一个目录,我们看见在我们输入密码后并没有去expecteof,这是由于ssh这个spawn并没有结束,并且自动操作时ssh实际上也不会自己结束除非你exit;所以你只能expectbash的提示符如何安装LINUX,其实也可以是机器名等linux set命令例子,这样才可以在远程创建一个目录。
注意,请不要用spawnmkdirtmpdir,这样会促使上一个spawn即ssh结束,这么你的tmpdir将在本机构建。
其实实际情况下可能会要你确认sshkey,可以通过并行的expect进行处理,不多赘言。
#4
最后一个demo是自己尝试写的,功能是安装python3.6.比较简单粗鲁,就是用spawn来开启不同的进程,并始终保持交互状态.这样做的缘由是之前扩写的时侯,使用send来执行指令总是有一些问题.后来发觉这样写出来也能work.暂时不晓得异同点,先贴上来请诸位指教.
#!/usr/bin/expect
set timeout 30
spawn apt-get install -y software-properties-common
interact
spawn add-apt-repository ppa:deadsnakes
expect "ENTER"
send "n"
interact
spawn apt-get update
interact
spawn apt-get install python3.6 -y
interact
本文原创地址://lrxjmw.cn/srjxegjjytdz.html编辑:刘遄,审核员:暂无