我需要一些EXPECT脚本的帮助....
我正在尝试在访问主机负载之前自动执行登录,并在用户输入错误密码时提供帮助。我首先获取用户名和密码,然后针对特定主机验证这一点。如果密码无效,我想循环并再次询问用户名和密码。
我正在尝试这个: -
(省略了几条不相关的行)
while {1} {
send_user "login as:- "
expect -re "(.*)\n"
send_user "\n"
set user $expect_out(1,string)
stty -echo
send_user "password: "
expect -re "(.*)\n"
set password $expect_out(1,string)
stty echo
set host "some-box.here.there.co.uk"
set hostname "some-box"
set host_unknown 0
spawn ssh $user@$host
while {1} {
expect {
"Password:" {send $password\n
break}
"(yes/no)?" {send "yes\n"}
"Name or service not known" {set host_unknown 1
break}
}
}
if {$host_unknown < 1} {
expect {
"$hostname#" {send "exit\r"
break
}
"Password:" {send \003
expect eof
close $spawn_id
puts "Invalid Username or Password - try again..."
}
}
} elseif {$host_unknown > 0} {
exit 0}
}
puts "dropped out of loop"
现在我可以去很多箱子做很多东西......
当我输入有效的用户名或密码,并且我的脚本关闭并完成我想要的所有其他内容时,这样可以正常工作,但当我输入无效密码时,我得到: -
Fred @ Aserver:〜$。/。EX_Test.sh ALL
登录为: - MyID
密码:spawn ssh MyID@some-box.here.there.co.uk
密码:密码: 用户名或密码无效 - 请重试...
登录为: - 找不到名为“exp6”的频道while executing "expect -re "(.*)\n"" invoked from within "if {[lindex $argv 1] != ""} { puts "Too many arguments" puts "Usage is:- Ex_Test.sh host|ALL"
} elseif {[lindex $ argv 0]!=“”} {
while {1} { ..." (file "./Ex_Test.sh" line 3)
它的行“无法找到名为”exp6“的频道,这真的让我烦恼。
我做错了什么?我正在阅读Exploring Expect(Don Lines)但无处可去......
答案 0 :(得分:1)
每当expect
等待某个词时,它会将该期望流程的spawn_id
保存到expect_out(spawn_id)
。
根据您的代码,期望在遇到
时生成spawn_id expect -re "(.*)\n"
当用户输入内容并按下回车键时,它将保存期望的spawn_id。如果您在调试时使用了expect,则可能在调试输出中看到了以下内容
expect does "" (spawn_id exp0) match regular expression "(.*)\n"
假设用户输入'Simon',那么调试输出将是
expect: does "Simon\n" (spawn_id exp0) match regular expression "(.*)\n"? Gate "*\n"? gate=yes re=yes
expect: set expect_out(0,string) "Simon\n"
expect: set expect_out(1,string) "Simon"
expect: set expect_out(spawn_id) "exp0"
expect: set expect_out(buffer) "Simon\n"
正如您所看到的,expect_out(spawn_id)包含它必须从中获取值的spawn_id
。在这种情况下,术语exp0
指向标准输入。
如果使用spawn
命令,那么正如您所知,tcl变量spawn_id
保存对进程句柄的引用,该句柄称为spawn句柄。我们可以通过显式设置进程句柄来使用spawn_id
,并将其保存以供将来参考。这是一个很好的部分。
根据您的代码,当您使用以下代码
给出错误密码时,您将关闭ssh连接close $spawn_id
利用spawn_id
,您正在执行此操作,而您缺少的是将expect
的进程句柄设置回原始引用句柄。即
While {1} {
###Initial state. Nothing present in spawn_id variable ######
expect "something here"; #### Now exp0 will be created
###some code here ####
##Spawning a process now###
spawn ssh xyz ##At this moment, spawn_id updated
###doing some operations###
###closing ssh with some conditions###
close $spawn_id
##Loop is about to end and still spawn_id has the reference to ssh process
###If anything present in that, expect will assume that might be current process
###so, it will try to expect from that process
}
当循环执行第二次时,expect会尝试期望来自spawn_id
句柄的命令,这只是ssh进程,这就是你得到错误的原因
can not find channel named "exp6"
请注意,“exp6”只是ssh进程的spawn句柄。
更新:
如果某个进程句柄可用
spawn_id
,然后expect
将始终期望来自该命令的命令 仅限流程。
也许您可以尝试以下内容来避免这些。
#Some reference variable
set expect_init_spawn_id 0
while {1} {
if { $expect_spawn_id !=0 } {
#when the loop enters from 2nd iteration,
#spawn_id is explicitly set to initial 'exp0' handle
set spawn_id $expect_init_spawn_id
}
expect -re "(.*)\n"
#Saving the init spawn id of expect process
#And it will have the value as 'exp0'
set expect_init_spawn_id $expect_out(spawn_id)
spawn ssh xyz
##Manipulations here
#closing ssh now
close $spawn_id
}
这是我的观点,可能不是有效的方法。您也可以考虑自己的逻辑来处理这些问题。