namespace import ::cisco::eem::*
namespace import ::cisco::lib::*

set errorInfo ""

#Opening CLI. If error, wit exists
#action_syslog priority info msg "Starting script for checking igmp process memory"

if [catch {cli_open} result] {
    error $result $errorInfo
    action_syslog priority info msg  "Error on script for checking memory allocated to igmp process: $result"
	exit
} else {
    array set cli $result
}

# check fo other script occurrences. Only one single script occurrence allowed at a single time. This is a measure to try not to have some scripts running in parallel.

if [catch {cli_exec $cli(fd) "show event manager scheduler thread detailed"} result] {
        error $result $errorInfo
		action_syslog priority info msg  "Error on script for checking memory allocated to igmp process: $result"
		exit
} else {
        set cmd_output $result
		set count 0
		set logg_output  [ split $cmd_output "\n" ]
		foreach item $logg_output {
			if {[regexp {689346255_igmp_memory_script_draft_4.tcl} $item matched]} {
				incr count
				}
		}
		if {$count != 1} {
				cli_close $cli(fd) $cli(tty_id)
				action_syslog priority info msg "One instance of script running, script execution has finished."
				exit
		}
}


# check if all required environment variables exist
# If any required environment variable does not exist, print out an error msg and quit
if {![info exists igmp_memory_threshold]} {
	action_syslog priority info msg "Policy cannot be run: variable igmp_memory_threshold has not been set"
	cli_close $cli(fd) $cli(tty_id)
	exit
}

# We need the job_id of igmp process. It is currently (2020/07/17) 1191 on all IPTV routers, but it may change.
# job_id is inititalized at -1. If it remains at -1, something went wrong with the output of "show processes igmp"
# "regsub -all {\s} $item {} string" trims spaces from the line.

set job_id -1
if [catch {cli_exec $cli(fd) "show processes igmp"} result] {
        error $result $errorInfo
		action_syslog priority info msg  "Error on script for checking memory allocated to igmp process: $result"
		exit
} else {
		set cmd_output $result
		set logg_output  [ split $cmd_output "\n" ]
		foreach item $logg_output {
			regsub -all {\s} $item {} string
			#action_syslog priority info msg $string
			if {[regexp {JobId:(\d+)} $string aux job_id] } {
				#action_syslog priority info msg $job_id
				break
			}
		}
	}

#We confirm that job_id for igmp has some logical value

if {$job_id < 0} {
	set b "Error on script for checking memory allocated to igmp process: Job_id for igmp process is inconsistent: "
	append b $job_id
	action_syslog priority info msg $b 
	exit
} 

#Preparring the command to check memory igmp process is using.

set command "show process memory detail "
append command $job_id
#action_syslog priority info msg  $command

# collect the command, add it to a file (one file per day) and check memory against a threshold. It threshold is crossed,  

if [catch {cli_exec $cli(fd) $command} result] {
        error $result $errorInfo
		action_syslog priority info msg  "Error on script for checking memory allocated to igmp process: $result"
		exit
} else {
		set cmd_output $result
		set logg_output  [ split $cmd_output "\n" ]
		foreach item $logg_output {
			regsub -all {\s} $item {} string
			if {[regexp {(\d+)Migmp} $string aux igmp_memory ]} {
				#set tdate [clock format [clock seconds] -format %Y%m%d]
				#set filename  [format "/harddisk:/scripts/igmp_memory_collection_%s.txt" $tdate]
				#set outfile [open $filename a]
				#set collected_line [clock format [clock seconds] -format  %Y%m%d%H%M%S]
				#set collected_line "" 
				#append collected_line "Script: Memory allocated to igmp = "
				#append collected_line $igmp_memory
				#puts $outfile $collected_line
				#close $outfile
				if { $igmp_memory > $igmp_memory_threshold} {
					set a "Script: Memory allocated to igmp crossed threshold. Current value = "
					append a $igmp_memory
					action_syslog priority err msg $a
					break
				}
			}
		}
	}
#closing cli and file
#action_syslog priority info msg "File closed, script execution has finished."
cli_close $cli(fd) $cli(tty_id) 

Tool Command Language(TCL) online compiler

Write, Run & Share TCL code online using OneCompiler's TCL online compiler for free. It's one of the robust, feature-rich online compilers for TCL language, running the latest TCL version 8.6. Getting started with the OneCompiler's TCL editor is easy and fast. The editor shows sample boilerplate code when you choose language as TCL and start coding.

Taking inputs (stdin)

OneCompiler's TCL online editor supports stdin and users can give inputs to programs using the STDIN textbox under the I/O tab. Following is a sample TCL program which takes name as input and prints hello message with your name.

set name [gets stdin]
puts "Hello $name"

About TCL

Tool Command Language(TCL) is a general purpose scripting language which is commonly used for GUIs and for testing. Everything is by default string in TCL. It was created by John Osterhout in 1989.

Syntax help

Variables

Variable is a identifier which is used to hold the value. set is used to create variables.

Examples

set name onecompiler

Loops

1. If-Else:

When ever you want to perform a set of operations based on a condition IF-ELSE is used.

if(conditional-expression) {
   #code
} else {
   #code
}

You can also use if-else for nested Ifs and If-Else-If ladder when multiple conditions are to be performed on a single variable.

2. Switch:

Switch is an alternative to If-Else-If ladder.

switch(conditional-expression) {    
value1 {     
 # code
}    
value1 {     
 # code
}    
...
default {
# code
} 

3. For:

For loop is used to iterate a set of statements based on a condition.

for{start}{test}{next}{  
  # code  
} 

4. While:

While is also used to iterate a set of statements based on a condition. Usually while is preferred when number of iterations are not known in advance.

while(condition) {  
 # code 
}  

Arrays

Array is a collection of similar data which is stored in continuous memory addresses. Array values can be fetched using index. Index starts from 0 to size-1.

Syntax

set ArrayName(Index) value

Procedures

Procedure is a sub-routine which contains set of statements. Uusually procedures are required when multiple calls are made to same set of statements. Procedures increases re-usuability and modularity.

Syntax

proc procedureName {arguments} {
   # code
}