Building network automation solutions

9 module online course

Start now!

Continuous display of top CPU processes

When you have to monitor which processes consume router’s CPU over a period of time, a Tcl script that emulates the Unix top command might come handy. The following Tcl script continuously displays top 20 Cisco IOS processes and refreshes the update every 5 seconds.

The following text written by Ivan Pepelnjak in 2008 was originally published on CT3 wiki. That web site became unreachable in early 2019; we retrieved the original text from the Internet Archive and republished it on blog November 17, 2020


  • Download the source file into flash:top.tcl.
  • Configure alias exec top tclsh flash:top.tcl.
  • Invoke with top.

Usage guidelines

Usage: top [ 5sec | 1min | 5min ]

The script changes the escape character to Ctrl/C. Use terminal escape default to restore default settings

If anyone discovered a reliable technique that detects a keypress event (= character available on stdin) in the Tcl loop, please let me know. The Ctrl/C solution is a kludge.

Source code

# title:    Emulate the Unix top command
# name:     top.tcl
# desc:     The script displays top CPU processes every 5 seconds
# ios config:
#           * download the file into flash:top.tcl
#           * configure alias exec top tclsh flash:top.tcl
#           invoke with top [5sec|1min|5min]

set IOS [string equal $tcl_platform(os) "Cisco IOS"];

if { $IOS } { 
  exec "terminal international"; 
  exec "terminal escape 3";

set arg [lindex $argv 0];
if { [string length $arg] == 0 } { set arg "5sec" } ;
if { [lsearch -exact { 5sec 1min 5min } $arg] < 0 } {
  puts {Usage: top [5sec|1min|5min]};
  return 0;

fconfigure stdout -buffering none;

while {1} {
  set lines [split [exec "show process cpu sorted $arg | exclude 0.00% +0.00% +0.00%"] "\n"];

  puts -nonewline "\033\[2J\033\[H";
  for { set lc 1 } { $lc < 23 } { incr lc } {
    set curline [lindex $lines $lc];
    if { [string length $curline] > 0 } { puts "$curline"; }
  puts -nonewline "\nBreak with Ctrl/C --> ";
  after 5000;


  1. Ivan, in latest IOS (12.2(33)SRC) you can use the "monitor" keyword in various show commands to accomplish the same thing: monitor something continuously.

    router#sh proc cpu monitor interval 5

    But i always enjoy your tcl (& eem) approaches ;)
  2. Thanks mate, Cool :)
  3. @Tassos: I've only found the "monitor" keyword in the "show proc cpu" and "show int" command. Check with show parser dump exec | inc show.*[a-z]+.*monitor interval.
  4. Tassos,
    I can't find anything like monitor interval in my routers.. :)

    Mr Ivan,
    Well, I would love to replace your show process command with this

    set lines [split [exec "show process cpu sorted $arg | exc 0.00%__0.00%__0.00% "] "\n"];

    This way you can list only the process being used for Router instead of all (long list)
  5. @Ivan : I guess "various" got interpreted as more than 2 ;)
    At least these 2 commands are the most used when referring to a continuous "show" operation.

    @massood, you need the latest 12.2(31)SB or 12.2(33)SRC to see it. Not all platforms support these releases.
  6. You're absolutely right ... various could also mean two :))

    I learn something new every day ;)
  7. "terminal exec prompt timestamp" is also interesting to know the CPU utilization each time a command is typed.
  8. Tassos, does the <show> have any impact on the routers performance?</show>
  9. Ivan, your script is very useful - I've been using it on 12.4(12c). But on 15.0(1r)M9 it does not clear the screen. If I execute "terminal international" and "terminal escape 3" BEFORE I start the script than it's ok. Any idea why?

    Also, if numbers under "Invoked" get too big the lines wrap so I modified output to:

    set curline [lindex $lines $lc];
    # if { [string length $curline] > 0 } { puts "$curline"; }
    set cutline "[string range $curline 0 78]"
    if { [string length $curline] > 0 } { puts "$cutline"; }

    Hope you don't mind :)
  10. The "terminal international" command is needed to enable router to send the escape character (chr(27)) as one character, not as ^[ sequence.
Add comment