TCL (pronounced "tickle") is a simple and powerful scripting language that lets you program functions in the CLI of the Sun Secure Application Switch. The CLI includes a TCL interpreter and supports TCL Version 8.3.3. TCL commands are fully integrated with the CLI, so that you do not have to change environments or shells. The CLI includes only basic TCL built-in commands and it does not include TK (GUI Toolkit), Safe TCL, other TCL extensions, or command reference documentation (man pages).
This document does not explain how to use TCL or describe the syntax for the supported TCL commands. If you are unfamiliar with using TCL, refer to http://www.tcl.tk.
The following table lists the TCL commands that the CLI supports.
Command | Description |
---|---|
append
|
Append to a variable. |
array
|
Manipulate array variables. |
auto_import
|
Determine whether specified imported commands reside in an autoloaded library and load the commands. |
auto_load
|
Attempt to load the definition for a command. |
auto_qualify
|
Compute a list of fully qualified names for a command. |
binary
|
Insert and extract fields from binary strings. |
break
|
Abort a looping command. |
case
|
Evaluate one of several scripts, depending on a pattern match.
(This command is deprecated. Use the switch command instead.)
|
catch
|
Evaluate a TCL script and trap exceptional returns. |
cd
|
Change working directory. |
close
|
Close an open channel. |
concat
|
Join (concatenate) lists. |
continue
|
Skip to the next iteration of a loop. |
cp
|
Copy a file to a specified destination. |
eof
|
Check for end-of-file condition on a channel. |
error
|
Generate an error and display a message. |
eval
|
Evaluate a TCL script. |
expr
|
Evaluate an expression. |
fblocked
|
Determine whether the last input operation exhausted all available input. |
fconfigure
|
Set and retrieve options on a channel. |
fcopy
|
Copy data from one channel to another. |
file
|
Manipulate a file and its attributes. |
for
|
Execute a loop. |
foreach
|
Iterate over all elements in one or more lists. |
format
|
Format a string in the same way as the ANSI C sprintf command.
|
gets
|
Read the next line from a channel. |
glob
|
Return names of files that match patterns. |
global
|
Access global variables instead of local variables. |
if
|
Execute a TCL script conditionally. |
incr
|
Increment the value of an integer variable. |
info
|
Return information about the state of the TCL interpreter (for example, variables and procedures). |
join
|
Create a string by joining the elements of a list. |
lappend
|
Append elements of a list to a variable. |
lindex
|
Retrieve an element from a list. |
linsert
|
Insert elements into a list. |
list
|
Create a list. |
llength
|
Count the number of elements in a list. |
lrange
|
Return a new list containing sequential elements from an existing list. |
lreplace
|
Return a new list formed by replacing elements of a list with new elements. |
ls
|
List the contents of a directory. A Sun addition. |
lsearch
|
Determine whether a list contains a particular element. |
lsort
|
Sort the elements of a list and return a new list in sorted order. |
mkdir
|
Create a directory. |
mv
|
Move a file to a specified destination. |
namespace
|
Create and manipulate contexts for commands and variables. |
open
|
Open a file, serial port, or command pipeline and return a channel identifier. |
package
|
Manipulate a database of packages available for use by the current TCL interpreter. |
pause
|
Pause a TCL script for a specified number of seconds. |
pid
|
Retrieve process id(s). |
proc
|
Create a TCL procedure. |
puts
|
Write characters to a channel. |
pwd
|
Return the path name of the current working directory. |
read
|
Read characters from a channel. |
regexp
|
Determine whether a regular expression matches a string. |
regsub
|
Substitute strings in variables using regular expression pattern matching. |
rename
|
Rename or delete a TCL command. |
return
|
Return from the current procedure. |
rm
|
Removes a file or directory. |
scan
|
Parse a string using conversion specifiers in the same way as the ANSI C sscanf command. |
seek
|
Change the current access position for an open channel. |
set
|
Create, read, or write a variable. |
source
|
Pass a file to the TCL interpreter as a text script. |
split
|
Split a string into a proper TCL list. |
string
|
Manipulate a string in various ways, for example, compare, search, and character type. |
subst
|
Substitute variables, commands, and backslashes in a string. |
switch
|
Evaluate one of several scripts, depending on a pattern match. |
tell
|
Return the current access position in an open channel. |
tclflush
|
Flush any output that has been buffered for a channel. |
trace
|
Execute a TCL command whenever a given variable is accessed. |
unknown
|
Handle attempts to invoke non-existent TCL commands. |
unset
|
Delete one or more variables. |
uplevel
|
Execute a script in a different level of the procedure calling stack. |
upvar
|
Create a link to a variable in a different level of the procedure calling stack. |
variable
|
Create and initialize a namespace variable. |
while
|
Execute a script repeatedly as long as a Boolean condition is true. |
Consider the following guidelines when you use TCL:
expr
is a valid command, but EXPR
is not.?
query does not return any TCL commands or keywords and
pressing the [Tab] key does not complete any TCL commands or keywords. TCL
error messages, however, do provide some syntax help. For example:.tclshrc
in directory
/ftl0
. If this file is present, the TCL
interpreter evaluates it when the CLI first starts.TCL commands accept both decimal and hexadecimal numbers, and return decimal numbers. For example:
sun> set num 0xf 0xf sun> incr num 16 sun> puts $num 16 sun> expr pow($num,4) 65536.0 sun> expr 0xa * 10 100
The ls
command lists the contents of a
directory.
ls [-a] [-l] [name ...
]
Argument | Description |
---|---|
-a
|
List all files, including hidden files beginning with a period (.).
|
-l
|
List contents in long format, which includes directory designator, user/group/other permissions (read, write, execute), size in bytes, date and time last modified, and name. Subdirectory names end with a slash (/).
|
name ...
|
Display information about the named files or directories. You must enter the full file or directory name(s). Wildcards are not allowed.
Without this argument, the
ls command
lists the contents of the current directory.
|
In this example, the ls
command, without any
arguments, shows a listing of the current directory.
sun> ls Directory '/ftl0/' nosConfig errhnd evtMgr.elf.stub halagent.elf.stub logMgr.elf.stub ui.elf.stub lib/ cdb.bak cdb.dat
In this example, the ls -l
command shows a
detailed listing of the files in the current directory.
sun> ls -l Directory '/ftl0/' -rw-rw-rw- 180 1 Jan 2002 00:10:35 nosConfig -rw-rw-rw- 9999 14 Jan 2002 16:48:45 errhnd -rw-rw-rw- 4616 14 Jan 2002 16:50:06 evtMgr.elf.stub -rw-rw-rw- 4616 14 Jan 2002 16:50:08 halagent.elf.stub -rw-rw-rw- 4616 14 Jan 2002 16:50:10 logMgr.elf.stub -rw-rw-rw- 4616 14 Jan 2002 16:50:44 ui.elf.stub drwxrwxrwx 512 1 Jan 2002 00:04:12 lib/ -rw-rw-rw- 649 9 Jan 2002 19:08:55 cdb.bak -rw-rw-rw- 685 14 Jan 2002 16:51:25 cdb.dat sun>
In this example, the ls -l
command with a file
name shows a detailed listing for the specified file.
sun> ls -l cdb.dat -rw-rw-rw- 685 14 Jan 2002 16:51:25 cdb.dat
The pause
command lets you pause a TCL script
or the CLI. This command is a Sun addition.
pause
seconds
Argument | Description |
---|---|
seconds
|
The number of seconds to pause. The valid range is 0 through 4294967295.
|
In this example, the pause
command inserts a
30-second pause in the script.
sun# proc test args { vSwitch create pause 30 puts "vSwitch is fully up and working." }
This section contains simple examples of using TCL with the CLI to quickly complete configuration tasks.
sun(config)# foreach i {eng pubs fin} {vSwitch $i; exit; }; create new vSwitch "eng" ? (y or n): y ......................................... create new vSwitch "pubs" ? (y or n): y ......................................... create new vSwitch "fin" ? (y or n): y ......................................... sun(config)# show vSwitch Name: eng ID: 2 Description: N/A Admin State: enabled Operational Status: up Name: fin ID: 4 Description: N/A Admin State: enabled Operational Status: up Name: pubs ID: 3 Description: N/A Admin State: enabled Operational Status: up Name: system ID: 0 Description: System vSwitch Admin State: enabled Operational Status: up
This example shows how to use TCL to create a variable that you can use in CLI commands. The variable in this example represents an IP address for an NTP server. You can use the variable in CLI commands instead of entering the server's IP address.
Note:Variables persist only for the duration of
the current CLI session. If you restart the CLI, you must
re-create any TCL variables.
|
sun(switchServices)# set ip 172.26.3.10 172.26.3.10 sun(switchServices)# ntp primary $ip minpoll 256 maxpoll 2048 sun(switchServices)# show ntp * $ip Server type: Primary Server IP Address: 172.26.3.10 Server Preference: N/A Burst Mode: N/A Min. Poll Interval: 256 Max. Poll Interval: 2048 Version: N/A sun# event sun(event)# syslog $ip loglevel warning sun(event)# show syslog $ip SysLog Syslog Log Host Port Level 172.26.3.10 N/A warning
The TCL interpreter displays descriptive error messages if you enter invalid commands or keywords, or if an operation fails. The following table lists the common error messages.
Command and error
|
Description and solution
|
---|---|
sun# append [Enter] wrong # args: should be "append varName ?value value ...?" |
The command is incomplete, and the error message displays the correct syntax. Enter the command with its required arguments.
|
sun# ntp sec $pi can't read "pi": no such variable |
The variable does not exist. Create a variable before you use it.
Variables persist only for the duration of the current CLI
session. If you restart the CLI, you must re-create any TCL
variables. Use the TCL
info vars
command to display current variables. Variables are
case-sensitive. Correct any typing errors.
|
sun# ls -l foo.txt Could not stat 'foo.txt': No such file or directory. |
The file does not exist in the current directory. This result is not necessarily an error; the file may be in a different directory. Check the file name and correct any typing errors.
|
sun# Expr 64 ^ 8 ERROR: "Expr" is not a recognized command |
TCL commands are case-sensitive and are lowercase. Enter the command in all lowercase characters.
|
sun# set pi 3.14159 3.14159 sun# incr pi expected integer but got "3.14159" |
You can increment only integer variables. Use
expr to add to a real variable, or change the
variable to an integer.
|
sun# expr pi * 5 syntax error in expression "pi * 5" |
Prefix a variable with $ to substitute its value in a command. In
this example, use
$pi .
|
Using TCL scripts in conjunction with the SCRIPT health check probe type enables you to write customized server health checks to verify real service availability. Executed within the virtual switch that is running the server health check, the script can range from simple TCL commands to complicated protocol-specific server health checks. Sharing many of the same arguments that define the other types of health checks, scripted health checks also have specific parameters such as scriptFile, scriptCommands, and scriptArgs.
The most significant difference between scripted health checks and the other types of health checks is the higher volume of system resources required by scripted health checks. Rather than performing the protocol-level exchange directly from a single application like the other health check types, the scripted health check process creates a task to run a new, freshly initiated TCL interpreter each time a script is executed. Although a new, separate interpreter ensures the same predictable starting point for each server probe, this task places a great demand on system resources.
The execution of a scripted health check begins with the evaluation of the TCL scriptFile (when specified). Although the script file can contain TCL commands, it is recommended that the file contain TCL procedures. These procedures can then be launched by the scriptCommands argument. This is an easier way of writing scripts and provides an additional method for passing arguments.
If no errors are detected during the evaluation, the script commands, which can be simple TCL commands or process execution statements, are executed. During command execution, TCL errors, indicating a failure, are reported. To ensure that a success status is reported if there are no TCL errors, you can use script logic to set a particular error code as an "exit code." An exit code of 0 indicates success; a non-zero exit code indicates failure. If an exit code is not set, and no TCL errors are reported, successful execution is assumed.
The following topics describe:
An example is also provided to show how to use TCL scripts with scripted server health checks.
Real service target information is passed by the following global variables used within a defined TCL procedure.
global shc_real_service_ip
global shc_real_service_port
Optional global arguments may be available, depending on the configuration of the scripted health check profile.
global shc_arg1
global shc_arg2
global shc_arg3
global shc_arg4
global shc_state_info
- Can be used to return state information about the
last execution of the script. This value will then be available for the
next script execution of the probe. The state information can include
values such as the status of the previous script run, an incrementing
counter, or a history summary. This variable can contain string data
between 0 and 32 characters in length.global shc_exit_code
- Can be used to indicate the successful execution of
the script. The return of 0 indicates a successful execution; the return
of non-zero indicates failure. The exit code can also be used to signal
different types of errors to give more visibility into the cause of the
error. For example, you could set an exit code of 4 to indicate a "page
not found" failure.The following are optional arguments for the SCRIPT health check profile. You set the values using the healthCheckProfile command.
scriptFile
text
scriptCommands
text
scriptArg1
text
scriptArg2
text
scriptArg3
text
scriptArg4
text
text
Note:If you specify a scriptFile in the
health check profile, it is recommended that the file contain
defined TCL procedures (proc). You should then use the
scriptCommands argument to launch the procedures with calling
arguments if required. Optionally, you can specify up to four
arguments in the health check profile.
|
The following are the arguments that are shared by all health check probe types.
seconds
probes
percentage
seconds
probes
The following example shows a test script file for use in scripted server health checks. Comments (#) are included in the file to describe the variables and arguments that are available.
proc shc-script-http { { probeLevel 0 } { debugMode 0 } } { # In the TCL proc, real service target information is passed using the # following global variables. global shc_real_service_ip global shc_real_service_port # # The following optional arguments may be used, depending on the # configuration of the SHC Profile for the scripted health check. # global shc_arg1 global shc_arg2 global shc_arg3 global shc_arg4 # The global variable shc_state_info stores script state, # which can be used to pass state information regarding the last # execution of the script. The variable can contain string data # between 0-32 chars in length. This value will be available for # the next probe's script exection. The script state can include # information such as the status of the previous run, an # incrementing counter, a history summary, or average successes. It # can be a single value, a list of values, or just a summary. # global shc_state_info # The global variable 'shc_exit_code' can be used to indicate script # execution success or failure. If it is not set, and there are no # other TCL errors, success is assumed. The possible values of the # shc_exit_code are 0 = success, non-zero = error. # global shc_exit_code # Initialize the returned error first, and clear it upon success. # set shc_exit_code 10 # Open a file to catch the output and dump the internal # variables that are available to the script. # # set dyn_output_file "/ftl0shc_$shc_real_service_ip_ # $shc_real_service_port.txt" # if { $debugMode != 0 } { set dyn_output_file "/ftl0/shc_" append dyn_output_file "$shc_real_service_ip" append dyn_output_file "p" append dyn_output_file "$shc_real_service_port" append dyn_output_file ".txt" set outputName "$dyn_output_file" # Open the file and rewrite it each time (w+) rather than appending # to it (a+) since appending will cause the file to grow rapidly. set gotError [ catch { set fname [ open "$outputName" w+ ] } ] catch { puts $fname " shc-script-http... " } catch { puts $fname " " } catch { puts $fname " Dynamic FileName: $dyn_output_file " } catch { puts $fname " calling arg : $calling_arg " } catch { puts $fname " RS IP Address: $shc_real_service_ip " } catch { puts $fname " RS Port Num: $shc_real_service_port" } catch { puts $fname " " } catch { puts $fname " State_Info: $shc_state_info " } catch { puts $fname " arg_1: $shc_arg1 " } catch { puts $fname " arg_2: $shc_arg2 " } catch { puts $fname " arg_3: $shc_arg3 " } catch { puts $fname " arg_4: $shc_arg4 " } catch { puts $fname " " } catch { puts $fname " " } } # Initialize the errors to zero # set sockError 0 set fconError 0 set putsError 0 set recvError 0 set rsSock "not-set" set stagesSet "" set inLIne "" if { $probeLevel > 1 } { append stagesSet "socket" set sockError [ catch { set rsSock [ socket $shc_real_service_ip $shc_real_service_port ] } ] } else { set rsSock "not-set and not-required" } if { $probeLevel > 2 } { append stagesSet " fconfig" set fconError [ catch { fconfigure $rsSock -buffering none -eofchar {} } ] }
if { $probeLevel > 3 } { append stagesSet " get" set putsError [ catch { puts -nonewline $rsSock "GET / HTTP/1.0\n\n" } ] }
if { $probeLevel > 4 } { append stagesSet " receive" set recvError [ catch { set inLine [ read $rsSock ] } ] } # Clean up the socket, if it was opened # if { $rsSock != "not-set" } { append stagesSet " closed-socket" catch { close $rsSock } } # Gather updated info about the current probe count, which will be used # to provide additional state information about the probe success or # failure. It will also provide a probe 'count' value in case it # is needed. # set l_len 0 catch { set l_len [ llength $shc_state_info ] } if { $l_len >= 5 } { set prev_probe [ lindex $shc_state_info 4 ] } else { set prev_probe 0 }
set probeCount [ expr $prev_probe + 1 ] # Summarize the errors, and set the appropriate return code and state info. # if { $sockError == 0 && $fconError == 0 && $putsError == 0 && $recvError == 0 }{ set shc_exit_code 0 set shc_state_info "prev probe was OK $probeCount" } else { set shc_exit_code 1 set shc_state_info "prev probe was NotOK $probeCount" } if { $debugMode != 0 } { catch { puts $fname " rsSock: $rsSock " } catch { puts $fname " inLine: $inLine " } catch { puts $fname " stages: $stagesSet " } catch { puts $fname " " } catch { puts $fname " exit code: $shc_exit_code " } catch { puts $fname " " } if { $shc_exit_code == 0 } { catch { puts $fname " Success! sock: $sockError, fconf: $fconError" } catch { puts $fname " puts: $putsError, recv: $recvError" } } else { catch { puts $fname " ERROR! sock: $sockError, fconf: $fconError" } catch { puts $fname " puts: $putsError, recv: $recvError" } } catch { close $fname } } } # proc shc-script-http