2016-04-11 8 views
1

Ich beabsichtige, telnet Verbindung mit einem Netzwerkgerät mit Expect und es beinhaltet das Senden von Befehlen an das Gerät mehrmals und Neustart auch das Gerät, damit die Telnet-Verbindung wieder und wieder.Zombie Telnet-Prozess stapeln bei der Verwendung von Spawn mit Expect

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 
} 

Auch wenn ich die Verbindung anmutig bin zu schließen, kann ich immer noch sehen, der Prozess (in Windows 7) in dem Task-Manager ausgeführt wird. (Auch bei Linux funktioniert der Telnet-Prozess als <defunct> Prozess).

Wenn ich das Skript über Nacht laufen lasse und sage, dass ich die Telnet-Verbindung etwa tausend Mal öffnen muss (da mein Skript das Gerät mehrmals neu startet und dadurch die Verwaltungsverbindung verloren geht), wird die Leistung reduziert.

Dies führt zu einem Speicherleck oder zu Fehlern in der Ressourcenzuordnung, wenn dies kontinuierlich geschieht.

Nach der Suche habe ich am Ende exp_close und exp_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.. 

Mit dem obigen Code wird exp_wait halten auf der Warteliste und es wird immer dort blockiert.

Um das gleiche zu vermeiden, habe ich auch -nowait Flagge verwendet, aber immer noch keine Verwendung. Es kehrt sofort zurück und der Prozess bleibt weiterhin im Prozessdiagramm.

Was sollte der optimale Weg sein, um mit diesem Problem umzugehen?

+0

Sie würden 'exp_close' verwenden, nachdem Sie' eof' gesehen haben. Sie möchten wahrscheinlich sehen, warum Sie Timeouts in Ihrem 'close_telnet_session'-Proc bekommen. –

+0

@glennjackman: Bei 'exp_close' endet die Fehlermeldung' spawn_id: spawn id exp4 not open', da 'Expec' bereits vom' telnet'-Prozess beobachtet wird. Übrigens habe ich '' timeout''-Handler in 'close_telnet_session' nur für den fehlersicheren Fall hinzugefügt. Es ist nicht so, dass ich "Timeout" erhalte, sondern eine Vorsichtsmaßnahme. – Dinesh

Antwort

0

Meiner Erfahrung nach werden erzeugte Prozessverbindungen normalerweise mit einem Aufruf von close beendet. Ist zu erwarten, dass Windows anders ist als erwartet * nix in dieser Hinsicht?

+0

'Schließen' funktioniert auch nicht und dieses Verhalten ist für Windows- und Linux-Systeme üblich. – Dinesh