【问题标题】:Problems looping to prompt for another password循环提示输入另一个密码的问题
【发布时间】:2014-09-03 13:35:27
【问题描述】:

我需要一些关于 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) 但一无所获......

【问题讨论】:

    标签: tcl expect


    【解决方案1】:

    每当expect 应该等待某个字时,它会将那个期望进程的spawn_id 保存到expect_out(spawn_id) 中。

    根据你的代码,expect的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_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_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
    }
    

    这是我的意见,它可能不是有效的方法。你也可以想出你自己的逻辑来处理这些问题。

    【讨论】:

    • 太棒了!一个非常清楚的解释,现在一切都说得通了。问题解决了,我可以破解了。非常感谢。
    猜你喜欢
    • 1970-01-01
    • 2014-04-12
    • 1970-01-01
    • 1970-01-01
    • 2016-07-03
    • 2011-12-08
    • 2012-07-25
    相关资源
    最近更新 更多