Forum Discussion
List all assigned variables
Is there a way within an iRule to list all of the assigned variables and their values without knowing the names of the variables? I'm looking for something like the 'set' or 'env' commands in bash.
6 Replies
- VernonWells
Employee
The tcl command ">http://www.tcl.tk/man/tcl8.0/TclCmd/info.htm" target="_blank">info vars will return a list of all variables that are visible in context of that command's evaluation. This doesn't give a 'name = value' set, providing rather a Tcl list of names, but before diving into how to accomplish name/value pair listing, it might be better to understand why you are seeking to do this. Presumably it is to facilitate testing or debugging in some fashion. Are you attempting to see whether a particular variable is defined? For that, ">http://www.tcl.tk/man/tcl8.0/TclCmd/info.htm" target="_blank">info exists is a better choice.
- VernonWells
Employee
Sorry. The DevCentral markup system, for some reason, mangled the actual hrefs. The Tcl 'info' command is documented here: http://www.tcl.tk/man/tcl8.0/TclCmd/info.htm. The command that dumps the variable names is 'info vars'. The command to check whether a variable exists is 'info exists'.
- Raj_Bhatia_1778
Nimbostratus
'info vars' is listing all the DG names. Can't see the variables (could be the list is too big and the log is truncated).
I also tried 'info local' (as per TCL documentation) but it returned blank.
Is the a documentation on info in devcentral or anywhere on the F5 website that I can refer?
I'm looking for a solution to unset all local variables, and would appreciate any help in this regards please.
Thanks!!
Hi Raj,
you may try the following...
set mytemp_var1 1 set mytemp_var2 1 set mytemp_var3 1 set mytemp_var4 1 set mytemp_var5 1 set mytemp_var6 1 set mytemp_var7 1 set mytemp_var8 1 set mytemp_var9 1 set mytemp_var10 1 set mytemp_var11 1 set mytemp_var12 1 set mytemp_var13 1 set mytemp_var14 1 set mytemp_var15 1 set mytemp_var16 1 set mytemp_var17 1 set mytemp_var18 1 set mytemp_var19 1 set mytemp_var20 1 log local0.debug "Classic \$mytemp_* variables: [info local mytemp_*]" set timestamp_start [clock clicks] eval "unset -nocomplain [info local mytemp_*]" set timestamp_stop [clock clicks] log local0.debug "Flushed the classic \$mytemp_* variables in [expr { $timestamp_stop - $timestamp_start - 2 }] clicks." log local0.debug "Leftover \$mytemp_* variables: [info local mytemp_*]"Log Output:
Rule /Common/AA_Debug1 : Classic $mytemp_* variables: mytemp_var13 mytemp_var14 mytemp_var15 mytemp_var16 mytemp_var17 mytemp_var18 mytemp_var1 mytemp_var20 mytemp_var19 mytemp_var2 mytemp_var3 mytemp_var4 mytemp_var5 mytemp_var6 mytemp_var7 mytemp_var8 mytemp_var10 mytemp_var9 mytemp_var11 mytemp_var12 Rule /Common/AA_Debug1 : Flushed the classic $mytemp_* variables in 31 clicks. Rule /Common/AA_Debug1 : Leftover $mytemp_* variables:... or if performance is a requirement for you then change your code to use $array(variables) ...
set mytemp(var1) 1 set mytemp(var2) 1 set mytemp(var3) 1 set mytemp(var4) 1 set mytemp(var5) 1 set mytemp(var6) 1 set mytemp(var7) 1 set mytemp(var8) 1 set mytemp(var9) 1 set mytemp(var10) 1 set mytemp(var11) 1 set mytemp(var12) 1 set mytemp(var13) 1 set mytemp(var14) 1 set mytemp(var15) 1 set mytemp(var16) 1 set mytemp(var17) 1 set mytemp(var18) 1 set mytemp(var19) 1 set mytemp(var20) 1 log local0.debug "Array \$mytemp variables: [array names mytemp]" set timestamp_start [clock clicks] unset -nocomplain mytemp set timestamp_stop [clock clicks] log local0.debug "Flushed the array \$mytemp variables in [expr { $timestamp_stop - $timestamp_start - 2 }] clicks." log local0.debug "Leftover \$mytemp variables: [array exists mytemp]"Log Output:
Rule /Common/AA_Debug1 : Array $mytemp variables: var16 var7 var17 var8 var18 var9 var20 var19 var1 var10 var2 var11 var3 var12 var13 var4 var14 var5 var15 var6 Rule /Common/AA_Debug1 : Flushed the array $mytemp variables in 3 clicks. Rule /Common/AA_Debug1 : Leftover $mytemp variables: 0Note: Using $array(variables) is much faster if you need to create AND delete them on each single request (aka. using per-request variables). Personally I always use four different kinds of $array(variables) in my own iRules. $static::global(), $session(), $conf() and $temp(). The $static::global() will store global configuration, the $session() variables will persist for an entire TCP session. The $conf() variables may changed/deleted as needed and $temp() variables will be flushed on each single request (or on demand if the containig data is large). This simple procedure makes the handling of $variables a no brainer even for the most complex iRules...
Cheers, Kai
- VernonWells
Employee
I'm curious what the intended use-case is. A variable declared outside of a namespace is scoped to the connection (in the sense of a "connection table" entry) and is destroyed when the connection closes. For something like HTTP, if one sets values in HTTP_REQUEST, the values will be overwritten for each HTTP Request message, even if they are multiplexed over a single TCP connection, because HTTP_REQUEST fires on each HTTP Request message. Ordinarily, one doesn't need to clean-up variable declarations manually.
Hi Vernon,
there exist some valid usecases to perfrom variable deletions, esp. if long living keep-alive connections are beeing used. I guess the most important ones are:
- Its frees memory at your wish (e.g. a set http_response [HTTP::payload] containig just 100kbyte for the entire connection lifetime instead of just a few CPU clicks to process the information will hurt)
- Its required if [info exists var_name] is used as controlstatement to trigger certain codeblocks based on previous (rare) conditions or to simplify the communication between independent events.
-
Using a well designed variable handling based on request "flows" (e.g. accessing 100 objects below of a certain /uri) will not overwrite an already existing variable on each request. It would remove/assign the variables just in the case a "flow change" occours (accesing a different /uri). See the example below...
when CLIENT_ACCEPTED { set session(flow) "" } when HTTP_REQUEST { unset -nocomplain temp if { [set $temp(low_path) [string tolower [HTTP::path]]] eq "/path1" } then { if { $session(flow) eq "path1" } then { Keep the configuration } else { set session(flow) "path1" unset -nocomplain conf set conf(param1) "xyz" set conf(param3) true set conf(param5) true set conf(param7) false set conf(param9) true set conf(param11) false set conf(param13) false set conf(param15) true } } else { if { $session(flow) eq "else" } then { Keep the configuration } else { set session(flow) "else" unset -nocomplain conf set conf(param1) "abc" set conf(param2) true set conf(param3) false set conf(param4) true set conf(param6) true set conf(param8) false set conf(param10) true set conf(param14) false set conf(param30) false set conf(param41) true } } if { [info exists conf(param1)] } then { Trigger codblock 1 set temp(string1) "50bytes" } # ... if { [info exists conf(param20)] } then { Trigger codeblock 20 set temp(string20) "100bytes" } } when HTTP_REQUEST_DATA { if { [info exists conf(param21)] } then { Trigger codeblock 20 set temp(request_payload) [HTTP::payload] Code of your choice... unset -nocomplain temp } # ... if { [info exists conf(param40)] } then { Trigger codeblock 40 set temp(string40) "50bytes" } } when HTTP_RESPONSE { if { [info exists conf(param41)] } then { Trigger codeblock 41 set temp(string41) "100bytes" } # ... if { [info exists conf(param60)] } then { Trigger codeblock 60 set temp(string) "20bytes" } } when HTTP_RESPONSE_DATA { if { [info exists conf(param61)] } then { Trigger codeblock 61 set temp(request_payload) [HTTP::payload] Code of your choice unset -nocomplain temp } # ... if { [info exists conf(param80)] } then { set temp(string) "20bytes" Trigger codeblock 80 } }
The more complex the content-switching scenario gets and the more independent ruleset and codeblocks are required to support the individual backend ressources, the more important a good variable handling will be.
Interesting note on using flow: I've also asked the F5 support to rollback the [pool] selection behavior in combination with [ONECONNECT] to the state of pre TMOS v12.1. Its now reverting the currently selected pool back to the default pool on each single HTTP request, so that the mentioned flow mechanic isn't able to offload the pool selections anymore (it has saved >10 CPU clicks on each single request in previous TMOS versions). ... 😞
Cheers, Kai
Help guide the future of your DevCentral Community!
What tools do you use to collaborate? (1min - anonymous)Recent Discussions
Related Content
* Getting Started on DevCentral
* Community Guidelines
* Community Terms of Use / EULA
* Community Ranking Explained
* Community Resources
* Contact the DevCentral Team
* Update MFA on account.f5.com