循环以提示另一个密码的问题

时间:2014-09-03 13:35:28

标签: tcl expect

我需要一些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)但无处可去......

1 个答案:

答案 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
}

这是我的观点,可能不是有效的方法。您也可以考虑自己的逻辑来处理这些问题。