【问题标题】:Expect while loop dies after 29th iteration期望 while 循环在第 29 次迭代后终止
【发布时间】:2023-09-12 07:25:01
【问题描述】:

我在 Cygwin 中使用 Expect 脚本。它读取两个输入文件:一个是按完整主机名列出的网络设备列表,另一个是在记录输出时在这些设备上运行的命令列表。它一直工作到完成第 29 个设备。当 spawn 命令在第 30 台设备上执行时,我得到以下输出:

send: spawn id exp65 not open
    while executing
"send -s "MyUserID\r""
    ("while" body line 30)
    invoked from within
"while {[gets $switches host] >= 0} {
        set hostname [string trimright $host]   ;# get rid of trailing whitespace
        if {[string length $hostname] == 0} {..."
    (file "./getna-lab.exp" line 37)

为了排除 Cygwin 的问题,我想在我通常使用 Expect 的 Mac 上进行测试,但我不能再做了(设备是安全的,只能通过 Windows 虚拟桌面使用,因此 Cygwin。)起初我以为这是因为 telnet 会话的“退出”不起作用并且它们保持打开状态,但事实并非如此;我尝试将“exit”添加到它肯定执行的命令列表文件中。

下面列出了脚本和其他文件内容。感谢您的帮助。

#!/usr/bin/expect

set timeout 600

log_user 0
match_max 100000
set expect_out(buffer) {}

set switchlist [lindex $argv 0]
set commandlist [lindex $argv 1]

#
# Open switch list file
#
if [catch {open "$switchlist" "r"} switches] {
    puts stderr "$CR$switches$CE\n"
    exit 1
}

#
# Verify command list file opens OK before we logon, etc.
#
if [catch {open "$commandlist" "r"} commands] {
    puts stderr "$CR$commands$CE\n"
    exit 1
}
close $commands

#
# Enable trace logging
#
trace variable expect_out(buffer) w log_by_tracing

#
# loop for each device in switch list, looping for each command in command list
#
while {[gets $switches host] >= 0} {
    set hostname [string trimright $host]   ;# get rid of trailing whitespace
    if {[string length $hostname] == 0} {   ;# leave loop if blank line detected
        break
        }
    regexp {^([^\..]+)(\..*$)} $hostname domain hostshort ;# peel off domain name
    send_user "\n$hostname:\nWorking...\n"
    if [catch {open "$commandlist" "r"} commands] {
        puts stderr "$CR$commands$CE\n"
        exit 1
    }
    log_file -noappend -a "$hostshort.txt"

        spawn telnet $hostname
        expect \
            {
            "sername:" {}
            "ogin:" {}
            "assword:" {send -s "\r" 
                            expect \
                                {
                                "ogin:" {}
                                "sername:" {}
                                }
                }
            timeout {
                send_user "Timed out on device $hostshort logon.\n"
                break
            }
        }

        send -s "myUserID\r"
        expect {
            "assword:" {}
            timeout {
                send_user "Timed out on device $hostshort logon.\n"
                break
            }
        }

        send -s "MyPassword\r"
        expect {
            "$hostshort" {}
            timeout {
                send_user "Timed out on device $hostshort logon.\n"
                break
            }
        }

        while {[gets $commands command] >= 0} {
            send -s "$command\r"
            expect {
                "$hostshort#" {}
                timeout {send_user "Timed out waiting for $hostshort # prompt.\n"}
            } 
        }
    send -s "exit\r"
log_file
}

close $switches
close $commands

我通常使用如下所示的 switchlist.txt 文件:

switch1.domainname.com
switch2.domainname.com

我还使用了一个名为 commands.txt 的文件,其中列出了如下命令:

show interface status
sh run

脚本通过

执行
# ./get-stuff.exp switchlist.txt commands.txt

【问题讨论】:

    标签: while-loop cygwin tcl expect


    【解决方案1】:

    我怀疑您可能会因为没有在该循环内正确关闭生成的进程而耗尽(某些东西)。尝试用这个替换循环的内容:

    spawn telnet $hostname
    expect {
        "sername:" { send -s "$myUserId\r"; exp_continue }
        "assword:" { send -s "MyPassword\r"; exp_continue }
        timeout {
            send_user "Timed out on device $hostshort logon.\n"
            continue   ;# next host
        }
        "$hostshort"
    }
    
    while {[gets $commands command] >= 0} {
        send -s "$command\r"
        expect {
            "$hostshort#" {}
            timeout {
                send_user "Timed out waiting for $hostshort # prompt.\n"
                continue   ;# next host
            }
        } 
    }
    send -s "exit\r"
    expect eof
    wait 
    exp_close
    

    【讨论】:

    • 好主意。虚拟终端很可能用完。只有相当少的数量可用; IIRC,它通常是 32 系统范围,有些用于除了期望之外的东西(例如运行期望的终端)。
    最近更新 更多