TCL 8.3(思科设备)实现CLI定时输出遇输入终止的问题
问题描述
需要实现每秒向CLI输出信息,检测到用户输入时停止输出循环,避免脚本无限运行。当前脚本使用gets stdin后会阻塞定时输出,无法同时执行两个任务;临时用计数限制循环,但效果不佳。运行环境为思科设备上的TCL 8.3。
现有代码
namespace eval vars { # counter as failsave set counter 1 } set stop 0 proc print_message {} { if {$::vars::counter == 50} { break } puts "Printing message..." incr ::vars::counter after 1000 print_message } # Start the message printing loop print_message # Check for user input while {!$stop} { set input [gets stdin] if {$input == "x"} { set stop 1 } } puts "Stopped printing messages"
临时方案运行示例
roPWB12#get lte history 50 1 16.02.2023 14:24:22 RSSI: -63 dB RSRP: -92 dB RSRQ: -7 dB SNR: 20.4 dB 25 16.02.2023 14:24:46 RSSI: -63 dB RSRP: -92 dB RSRQ: -7 dB SNR: 15.8 dB (-4.6) Press enter for another 50 measurements or enter new amount of repeats... 51 16.02.2023 14:34:23 RSSI: -63 dB RSRP: -92 dB RSRQ: -7 dB SNR: 21.2 dB (+5.4) 58 16.02.2023 14:34:30 RSSI: -63 dB RSRP: -92 dB RSRQ: -7 dB SNR: 20.2 dB (-1.0) Press enter for another 50 measurements or enter new amount of repeats... 100 101 16.02.2023 14:38:23 RSSI: -63 dB RSRP: -92 dB RSRQ: -7 dB SNR: 14.6 dB (-5.6) 140 16.02.2023 14:39:01 RSSI: -63 dB RSRP: -92 dB RSRQ: -7 dB SNR: 14.8 dB (+0.2) 184 16.02.2023 14:39:46 RSSI: -63 dB RSRP: -92 dB RSRQ: -7 dB SNR: 13.8 dB (-1.0) Press enter for another 100 measurements or enter new amount of repeats... 201 20.02.2023 11:18:15 RSSI: -64 dB (-1) RSRP: -97 dB (-5) RSRQ: -7 dB SNR: 12.6 dB (-1.2) 245 20.02.2023 11:18:58 RSSI: -64 dB RSRP: -97 dB RSRQ: -7 dB SNR: 21.2 dB (+8.6) 289 20.02.2023 11:19:43 RSSI: -64 dB RSRP: -97 dB RSRQ: -7 dB SNR: 17.8 dB (-3.4) Press enter for another 100 measurements or enter new amount of repeats... 7
解决方案
原脚本的核心问题是gets stdin为阻塞调用,会暂停TCL事件循环,导致after调度的定时任务无法执行。要同时实现定时输出和输入检测,需采用非阻塞式输入监听结合事件循环的方式:
修改后代码
namespace eval app { set running 1 set counter 0 } proc print_message {} { if {!$::app::running} { return } puts "Printing message [incr ::app::counter]..." after 1000 print_message } proc handle_input {} { if {[gets stdin input] >= 0} { # 输入x时停止输出循环 if {$input eq "x"} { set ::app::running 0 puts "\nStopped printing messages" # 移除stdin监听,避免重复触发 fileevent stdin readable {} } else { # 可扩展处理其他输入,如调整输出次数/间隔 puts "\nReceived input: $input" } } } # 启动定时输出任务 print_message # 设置非阻塞输入监听:当stdin有输入时自动调用handle_input fileevent stdin readable handle_input # 启动事件循环,保持脚本运行直到running变量改变 vwait ::app::running
关键说明
- 非阻塞输入监听:通过
fileevent stdin readable handle_input实现,不会阻塞事件循环,定时任务可正常执行。 - 状态控制:用
::app::running变量控制定时任务的启停,无需依赖计数限制。 - 事件循环维持:
vwait ::app::running让脚本持续运行,直到用户输入触发状态变更。
内容的提问来源于Stack Exchange,提问作者Mario Jost
相关产品推荐
相关产品推荐

