Total Pageviews

Saturday, April 14, 2012

TCL Shell in Cisco IOS

Were you ever in a situation where a file that would have to be on the router was sitting on your laptop, but you couldn't store it into the router's flash across the Telnet session or through the console port?

If the file in question is a text file, and the router supports Tcl shell, danshtr documented an interesting trick: you create the file in Tclsh interpreter, cut-and-paste the text through the telnet session into a Tcl string and write the string to the file. If you want to have a more cryptic solution here it is:

    * Start tclsh;
    * Enter puts [open "flash:filename" w+] {. Do not hit the ENTER key at the end of the line
    * Copy-paste the file contents. The contents should not include unmatched curly right brackets (every curly right bracket has to be preceded by a matching curly left bracket).
    * After the file contents have been pasted, enter } and press ENTER.
    * End the tclsh session with tclquit.
   
===============
Predefine your own Tcl functions

If you want to have your own Tcl functions available when you start tclsh, you could use the scripting tcl init file configuration command that I've briefly mentioned in one of the previous posts. This command specifies a source file that is executed every time you start Tcl shell. The source file can contain function definitions, package declarations or any other Tcl code.

If you need to, you can specify multiple initialization files.

For example, if you'd like to implement a comfortable Tcl-based pinger (similar to the one Ethan Banks found in the Sadikhov forums, store the following Tcl code into the file flash:pinger.tcl …

proc pinger { iplist } {
  foreach ip $iplist {
    if { [regexp "(!!!)" [exec "ping $ip timeout 1" ]] } {
      puts "$ip"
    } else { puts "$ip **** failed ***" }
  }
}

… and configure scripting tcl init flash:pinger.tcl. Now you can ping a number of hosts in a single operation:

R1#tclsh
R1(tcl)#pinger { 10.0.0.1 10.0.0.2 10.0.0.3 10.0.0.4 }
10.0.0.1
10.0.0.2
10.0.0.3 **** failed ***
10.0.0.4 **** failed ***
======================================
event manager applet WeekdayStart
 event timer cron name "WeekdayStart" cron-entry "1 9 * * 1-5"
 action 1.0 cli command "enable"
 action 2.0 cli command "clear ip route 172.18.1.0"
!
event manager applet WeekdayEnd
 event timer cron name "WeekdayEnd" cron-entry "1 17 * * 1-5"
 action 1.0 cli command "enable"
 action 2.0 cli command "clear ip route 172.18.1.0"

The cron-entry parameter in the event timer cron command specifies that the applet is run one minute after 9AM or 5PM (the reverse time/date order makes it particularly confusing) on every day of every month (the two asterisks) but only on weekdays (the 1-5 parameter for the day-of-week).

event manager applet midnight
event timer cron name midnight cron-entry "@midnight"
action 1.0 cli command "enable"
action 2.0 cli command "tclsh flash:midnight.tcl"
==========================   
Edit files using TCL
======================
First goto tclsh:

Router#tclsh

Now open the file. The w+ means that you will override the file.

Router(tcl)#set x [open "flash:a.txt" w+]
file0

Now run the first command "set lst {", then paste the content of the file and finish with "}"

Router(tcl)#set lst {
+>no access-list 100
+>access-list 100 per ip any host 1.1.1.1
+>}

no access-list 100
access-list 100 per ip any host 1.1.1.1

Now write the file and close it

Router(tcl)#puts $x $lst

Router(tcl)#close $x

Quit TCL

Router(tcl)#tclquit

Enjoy...

=========================
Run several commands at once
============================
First run tclsh:

Router#tclsh

Put the commands you want to run between the bracket signs {}:

Router(tcl)#set x {
+>conf t
+>int f0/0
+>ip addr 1.1.1.1 255.255.255.0
+>exit
+>exit
+>}

conf t
int f0/0
ip addr 1.1.1.1 255.255.255.0
exit
exit


Now execute the commands:

Router(tcl)#eval $x

Quit tclsh


==========================
Show commands and subcommands of regexp

# show_section.tcl
#
# syntax s_i "<regexp>"
#
# Returns: all headers of included lines with <regexp> in the line
# Author: Wyatt Sullivan
# Shameless Plug: http://www.bgp4.us
#
# Revision: 1.1
#
# Revision History:
#           1.1 - Fixed bug in using | in regexp
#           1.0 - Initial

proc s_i {reg_exp} {

 set sh_run [exec "sh run"]
 set header ""
 set final_out ""
 set line ""
 set header ""
 set printed_header 0
 set reg_exp "$reg_exp"

 foreach line [regexp -all -line -inline ".*" $sh_run] {
    if {[regexp "(^\[^ ])" $line]} {
       set header $line
       set printed_header 0
    }
    set cur_line [regexp -inline $reg_exp $line]
    set is_not_cur_line [regexp $cur_line ""]
    if { $is_not_cur_line == 0 } {
       if {![string equal $cur_line $header] && $printed_header == 0} {
          #puts $header
          append final_out $header
          set printed_header 1
       } 
       if {![string equal $cur_line $header]} {

          #puts $cur_line
          append final_out $line
       }
    }
  }

set hits [regsub -all "{|}" $final_out "" final_out]

return  $final_out
}

No comments:

Post a Comment