【发布时间】:2016-08-01 23:11:12
【问题描述】:
我打算使用Expect 与网络设备建立telnet 连接,这涉及多次向设备发送命令并重启设备。因此,我需要一次又一次地建立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_close 和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..
使用上面的代码,exp_wait 一直在等待并且被阻塞在那里。
为了避免同样的情况,我也使用了-nowait 标志,但仍然没有用。它立即返回,过程仍停留在流程图中。
处理此问题的最佳方法应该是什么?
【问题讨论】:
-
在看到
eof后,您会使用exp_close。你可能想看看为什么你的close_telnet_sessionproc 会超时。 -
@glennjackman :使用
exp_close,我最终得到spawn_id: spawn id exp4 not open错误消息,因为Expect已经从远程登录进程中观察到eof。顺便说一句,我在close_telnet_session中添加了timeout处理程序,只是为了防故障情况。不是我收到timeout,而是一种预防措施。
标签: linux process tcl expect telnet