Zombie telnet进程在使用与Expect的产卵时堆积起来

时间:2016-04-11 16:48:03

标签: linux process tcl expect telnet

我打算使用telnet与网络设备建立Expect连接,它涉及多次向设备发送命令,以及重启设备。因此,我需要一次又一次地建立telnet连接。

proc dputs {msg} {
    if {[info exists ::debug] && $::debug} {
        puts $msg
    }
}

proc open_telnet_session {} {
    set sResult FAIL 
    set prompt "(\r|\n|\r\n).*?(#|%|>|\\\$) $"
    #set prompt "#|%|>|\\\$ $"
    set timeout 60
    if {$::tcl_platform(platform) eq "windows"} {
        spawn {c:\Dinesh\telnet_32bit.exe} $::device_ip
    } else {
        spawn telnet $::device_ip
    }
    set ::device_ip $spawn_id
    expect {
        timeout {puts "Timeout happened while spawning telnet session";return $sResult}
        eof     {puts "EOF happened while spawning telnet session";return $sResult}
        "login: $" {send "$::device_uname\r";exp_continue}
        "password: $" {send "$::device_pwd\r";exp_continue}
        -re $prompt 
    }
    set sResult PASS 
    return $sResult
}


proc send_cmd_to_device {cmd} {
    set timeout 180
    dputs "cmd : $cmd"
    set sResult FAIL 
    set prompt "(\r|\n|\r\n).*?(#|%|>|\\\$) $"
    set ::spawn_id $::device_ip

    if {[catch {send "$cmd\r"} errorMsg]} {
        puts "Failed to send the commands..."
        puts "Reason : $errorMsg"
        return $sResult 
    }
    expect {
        timeout {puts "Timeout happened while sending commands to telnet session";return 0}
        eof     {puts "EOF happened while sending commands to telnet session";return 1}
        "invalid token" {puts "Invalid token error from device";exp_continue}
        "$cmd" { dputs "\n\n matching the cmd\n\n";set ::actual_cmd_match 1;exp_continue}
        -re $prompt {
            if {$::actual_cmd_match} {
                dputs "\n\n final prompt match \n\n"
                set ::actual_cmd_match 0
                set sResult PASS 
            } else {
                dputs "\n\n still waiting for prompt match \n\n"
                exp_continue
            }
        }
    }
    return $sResult
}
proc close_telnet_session {} {
    set sResult FAIL 
    set ::spawn_id $::device_ip
    #This will send 'Ctrl+]' to close the telnet connection gracefully
    if {[catch {send "\x1d"} errorMsg]} {
        puts "Failed to send the commands..."
        puts "Reason : $errorMsg"
        return $sResult 
    }
    expect { 
        timeout {return $sResult}
        eof {return $sResult}
        -nocase "telnet>"
    }
    if {[catch {send "quit\r"}]} {
        puts "Failed to send the commands..."
        puts "Reason : $errorMsg"
        return $sResult 
    }
    expect {
        timeout {return $sResult}
        eof {set sResult PASS}
    }
    return $sResult
}

即使我正在优雅地关闭连接,我仍然可以在任务管理器中看到该进程(在Windows 7中)。 (与Linux的情况相同,telnet进程显示为<defunct>进程)。

如果我一夜之间运行脚本并说我必须打开telnet连接大约数千次(因为我的脚本涉及多次重启设备,因此管理连接将丢失),它将最终降低性能。

当这种情况持续发生时,这将导致内存泄漏或资源分配失败。

经过大量搜索后,我最终得到exp_closeexp_wait

# Killing the process in Windows...
exec taskkill /pid $telnet_process_id
exp_close -i $::device_id 
exp_wait -i $::device_id; # This becomes a blocking call..

使用上面的代码,exp_wait会继续等待,并且在那里被阻止。

为了避免这种情况,我也使用了-nowait标志,但仍然没有用。它立即返回,并且该过程仍然保留在流程图中。

处理此问题的最佳方法是什么?

1 个答案:

答案 0 :(得分:0)

根据我的经验,生成的流程连接通常会在调用close时终止。在这方面,期望在* nix上的窗口与预期不同吗?