WAS v8.5 > Script the application serving environment (wsadmin) > Scripting concepts

Use wsadmin scripting with Jacl

Jacl is an alternate implementation of TCL, and is written entirely in Java code.

The wsadmin tool uses Jacl V1.3.2.


Stabilization of the Jacl syntax in wsadmin

The Jacl language stabilized in v7 of the product. IBM does not currently plan to deprecate or remove this capability in a subsequent release of the product; but future investment will be focused on the Jython language, which is the strategicalternative. We do not need to change any of your existing applications and scripts that use Jacl; but you should consider using the strategicalternative for new applications.

The Jython syntax for wsadmin is the strategic direction for WebSphere Application Server administrative automation. WAS v8.5 continues to provide enhanced administrative functions and tooling that support product automation and the use of the Jython syntax. The following Jython scripting-related enhancements are provided in the product:


Basic syntax

The basic syntax for a Jacl command is the following:

The command is either the name of a built-in command or a Jacl procedure. For example:

puts stdout {Hello, world!} 
=> Hello, world!

In this example, the command is puts which takes two arguments, an I/O stream identifier and a string. The puts command writes the string to the I/O stream along with a trailing new line character. The arguments are interpreted by the command. In the example, stdout is used to identify the standard output stream. The use of stdout as a name is a convention employed by the puts command and the other I/O commands. stderr identifies the standard error output, and stdin identifies the standard input.


Variables

The set command assigns a value to a variable. This command takes two arguments: the name of the variable and the value. Variable names can be any length and are case sensitive. We do not have to declare Jacl variables prior to using them. The interpreter will create the variable when it is first assigned a value. For example:

set a 5
=> 5
set b $a
=> 5

The second example assigns the value of variable a to variable b. The use of dollar sign ($) indicates variable substitution. We can delete a variable with the unset command, for example:

We can pass any number of variables to the unset command.

The unset command gives an error if a variable is not already defined. We can delete an entire array or just a single array element with the unset command. Using the unset command on an array is an easy way to clear out a big data structure. The existence of a variable can be tested with the info exists command. You might need to test for the existence of the variable because the incr parameter requires that a variable exist first, for example:


Command substitution

The second form of substitution is command substitution. A nested command is delimited by square brackets, [ ]. The Jacl interpreter evaluates everything between the brackets and evaluates it as a command. For example:

set len [string length my_string]
=> 6

In this example, the nested command is the following: string length my_string. The string command performs various operations on strings. In this case, the command asks for the length of the string my_string. If there are several cases of command substitution within a single command, the interpreter processes them from left bracket to right bracket. For example:

set number "1 2 3 4" 
=> 1 2 3 4
set one [lindex $number 0]
=> 1
set end [lindex $number end]
=> 4 
set another {123  456  789}   
=> 123  456  789
set stringLen [string length [lindex  $another  1]]
=> 3
set listLen [llength [lindex $another 1]
=> 1


Math expressions

The Jacl interpreter does not evaluate math expressions. Use the expr command to evaluate math expressions. The implementation of the expr command takes all arguments, concatenates them into a single string, and parses the string as a math expression. Once the expr command computes the answer, it is formatted into a string and returned. For example:

expr 7.2 / 3
=> 2.4


Backslash substitution

The final type of substitution done by the Jacl interpreter is backslash substitution. Use backslashes to add quotation characters that have special meaning to the interpreter. For example, we can specify a literal dollar sign, brace, or bracket by quoting it with a backslash. If we are using lots of backslashes, instead we can group things with curly braces to turn off all interpretation of special characters. There are cases where backslashes are required. For example:

set dollar "This is a string \$contain dollar char"
=> This is a string $contain dollar char

set x $dollar
=> This is a string $contain dollar char 

set  group {$ {} [] { [ } ]}
=> $ {} [] { [ } ]

We can also use backslashes to continue long commands on multiple lines. A new line without the backslash terminates a command. A backslash that is the last character on a line convert into a space. For example:

set  totalLength  [expr  [string  length  "first string"] + \
[string  length  "second string"]]
=> 25


Grouping with braces and double quotation marks

Use double quotation marks and curly braces to group words together. Quotation marks enable substitutions to occur in the group and curly braces prevent substitution. This rule applies to command, variable, and backslash substitutions. For example:

set s Hello
=> Hello

puts stdout "The length of $s is [string length $s]."
=> The length of Hello is 5.

puts  stdout  {The length of $s is [string  length  $s].}
=> The length of $s is [string length $s].

In the second example, the Jacl interpreter performs variable and command substitution on the second argument from the puts command. In the third command, substitutions are prevented so the string is printed as it is.

Special care must also be taken with path descriptions because the Jacl language uses the backslash character (\) as an escape character. To fix this, either replace each backslash with a forward slash, or use double backslashes in distributed path statements. For example: C:/ or C:\\


Procedures and scope

Jacl uses the proc command to define procedures. The basic syntax to define a procedure is the following:

The first argument is the name of the procedure being defined. The name is case sensitive, and in fact it can contain any characters. Procedure names and variable names do not conflict with each other. The second argument is a list of parameters to the procedures. The third argument is a command, or more typically a group of commands that form the procedure body. Once defined, a Jacl procedure is used just like any of the built-in commands. For example:

proc divide {x y} {
set result [expr $x/$y]
puts $result}

Inside the script, this is how to call divide procedure:

And it gives a result resembling the following:

It is not necessary to use the variable c in this example. The procedure body might also written as:

return  [expr  sqrt($a
  *  $a  +  $b
  *  $b)]

The return command is optional in this example because the Jacl interpreter returns the value of the last command in the body as the value of the procedure. So, the procedure body might be reduced to:

expr  sqrt($a
  *  $a  +  $b
  *  $b)

The result of the procedure is the result returned by the last command in the body. The return command can be used to return a specific value.

There is a single, global scope for procedure names. We can define a procedure inside another procedure, but it is visible everywhere. There is a different name space for variables and procedures therefore you might have a procedure and a variable with the same name without a conflict. Each procedure has a local scope for variables. Variables introduced in the procedures exist only for the duration of the procedure call. After the procedure returns, those variables are undefined. If the same variable name exists in an outer scope, it is unaffected by the use of that variable name inside a procedure. Variables defined outside the procedure are not visible to a procedure, unless the global scope commands are used.

The global scope is the top-level scope. This scope is outside of any procedure. You must make variables defined at the global scope accessible to the commands inside procedure using the global command.

The syntax for the global command is the following:


Comments

Use the pound character (#) to make comments.


Command-line arguments

The Jacl shells pass the command-line arguments to the script as the value of the argv variable. The number of command-line arguments is given by argc variable.

The name of the program, or script, is not part of argv nor is it counted by argc. The argv variable is a list. Use the lindex command to extract items from the argument list, for example:

set  first  [lindex  $argv  0]
set  second  [lindex  $argv  1]


Strings and pattern matching

Strings are the basic data item in the Jacl language. There are multiple commands used to manipulate strings. The general syntax of the string command is the following:

The operation argument determines the action of the string. The second argument is a string value. There might be additional arguments depending on the operation.

The following table includes a summary of the string command:

string command syntax descriptions. Run the string command with one or more arguments.

Command Description
string compare str1 str2 Compares strings lexicographically. Returns 0 if equal, -1 if str1 sorts precedes str2, else1.
string first str1 str2 Returns the index in str2 of the first occurrence of str1, or -1 if str1 is not found.
string index string1 index1 Returns the character at the specified index.
string last str1 str2 Returns the index in str2 of the last occurrence of str1, or -1 if str1 is not found.
string length string Returns the number of characters in the string.
string match pattern str Returns 1 if str matches the pattern, else 0.
string range str i j Returns the range of characters in str from i to j
string tolower string Returns string in lowercase.
string toupper string Returns string in uppercase.
string trim string ?chars? Trims the characters in chars from both ends of string. chars defaults to white space.
string trimleft string ?chars? Trims the characters in chars from the beginning of string. chars defaults to white space.
string trimright string ?chars? Trims the characters in chars from the end of string. chars defaults to white space.
string wordend str ix Returns the index in str of the character after the word containing the character at index ix.
string wordstart str ix Returns the index in str of the first character in the word containing the character at index ix.


The append command

The first argument of the append command is a variable name. It concatenates the remaining arguments onto the current value of the named variable. For example:

set  my_item  z
=> z
append  my_item a b c
=> zabc


The regexp command

The regexp command provides direct access to the regular expression matcher. The syntax is the following:

The return value is 1 if some part of the string matches the pattern. Otherwise, the return value is 0. The pattern does not have to match the whole string. If you need more control than this, we can anchor the pattern to the beginning of the string by starting the pattern with ^, or to the end of the string by ending the pattern with dollar sign, $. We can force the pattern to match the whole string using both characters. For example:

set  text1  "This is the first string"
=> This is the first string

regexp  "first string" $text1
=> 1

regexp "second string"  $text1
=> 0


Jacl data structures

The basic data structure in the Jacl language is a string. There are two higher level data structures: lists and arrays. Lists are implemented as strings and the structure is defined by the syntax of the string. The syntax rules are the same as for commands. Commands are particular instances of lists. Arrays are variables that have an index. The index is a string value so we can think of arrays as maps from one string (the index) to another string (the value of the array element).


Jacl lists

The lists of the Jacl language are strings with a special interpretation. In the Jacl language, a list has the same structure as a command. A list is a string with list elements separated by white space. We can use braces or quotation marks to group together words with white space into a single list element.

The following table includes commands related to lists:

list command syntax descriptions. Run the list command with one or more arguments.

Command Description
list arg1 arg2 Creates a list out of all its arguments.
lindex list i Returns the i'th element from list.
llength list Returns the number of elements in list.
lrange list i j Returns the i'th through j'th elements from list.
lappend listVar arg arg ... Appends elements to the value of listVar
linsert list index arg arg ... Inserts elements into list prior to the element at position index. Returns a new list.
lreplace list i j arg arg ... Replaces elements i through j of list with the args. Return a new list.
lsearch mode list value Returns the index of the element in list that matches the value according to the mode, which is -exact, -glob, or -regexp, -glob is the default. Return -1 if not found.
lsort switches list Sorts elements of the list according to the switches: -ascii, -integer, -real, -increasing, -decreasing, -command command. Return a new list.
concat arg arg arg ... Joins multiple lists together into one list.
join list joinString Merges the elements of a list together by separating them with joinString.
split string splitChars Splits a string up into list elements, using the characters in splitChars as boundaries between list elements.


Arrays

Arrays are the other primary data structure in the Jacl language. An array is a variable with a string-valued index, so we can think of an array as a mapping from strings to strings. Internally an array is implemented with a hash table. The cost of accessing each element is about the same. The index of an array is delimited by parentheses. The index can have any string value, and it can be the result of variable or command substitution. Array elements are defined with the set command, for example:

Substitute the dollar sign ($) to obtain the value of an array element, for example:

For example:

set fruit(best) kiwi
=> kiwi

set fruit(worst) peach
=> peach

set fruit(ok) banana
=> banana

array get fruit
=> ok banana worst peach best kiwi

array exists fruit
=> 1

The following table includes array commands:

array command syntax descriptions. Run the array command with an argument.

Command Description
array exists arr Returns 1 if arr is an array variable.
array get arr Returns a list that alternates between an index and the corresponding array value.
array names arr ?pattern? Return the list of all indexes defined for arr, or those that match the string match pattern.
array set arr list Initializes the array arr from list, which need the same form as the list returned by get.
array size arr Returns the number of indexes defined for arr.
array startsearch arr Returns a search token for a search through arr.
array nextelement arr id Returns the value of the next element in array in the search identified by the token id. Returns an empty string if no more elements remain in the search.
array anymore arr id Returns 1 if more elements remain in the search.
array donesearch arr id Ends the search identified by id.


Control flow commands

The following looping commands exist:

The following are conditional commands:

The following is an error handling command:

The following commands fine-tune control flow:


if then else

The if command is the basic conditional command. It says that if an expression is true, then run the second line of code, otherwise run a different line of code. The second command body (the else clause) is optional.

The syntax of the command is the following:

The then and else keywords are optional. For example:

if {$x == 0} {
 puts stderr "Divide by zero!"} else {
 set slope [expr $y/$x]}


switch

Use the switch command to branch to one of many commands depending on the value of an expression. Choose based on pattern matching as well as simple comparisons. Any number of pattern-body pairs can be specified. If multiple patterns match, only the code body of the first matching pattern is evaluated. The general form of the command is the following:

We can also group all the pattern-body pairs into one argument:

There are four possible flags that determine how value is matched.

For example:

switch  -exact  --  $value  {
 foo  {doFoo;  incr  count(foo)}
 bar {doBar;  return  $count(foo)}
 default   {incr  count(other)}}

If the pattern associated with the last body is default, then the command body is started if no other patterns match. The default keyword works only on the last pattern-body pair. If we use the default pattern on an earlier body, it is treated as a pattern to match the literal string default.


foreach

The foreach command loops over a command body and assigns a loop variable to each of the values in a list. The syntax is the following:

The first argument is the name of a variable. The command body runs one time for each element in the loop with the loop variable having successive values in the list. For example:

set numbers {1 3 5 7 11 13}
foreach num $numbers {
puts $num}

The result from the previous example is the following output, assuming that only one server exists in the environment. If there is more than one server, the information for all servers returns:

1
3
5
7
11
13


while

The while command takes two arguments; a test and a command body, for example:

The while command repeatedly tests the boolean expression and runs the body if the expression is true (non-zero). For example:

set i 0
while {$i < 5} {
puts "i is $i"
incr i} 

The result from the previous example resembles the following output, assuming there is only one server. If there is more than one server, it prints all of the servers:

i is 0
i is 1
i is 2
i is 3
i is 4


for

The for command is similar to the C language for statement. It takes four arguments, for example:

The first argument is a command to initialize the loop. The second argument is a boolean expression which determines if the loop body runs. The third argument is a command that runs after the loop body: For example:

set numbers {1 3 5 7 11 13}
for {set i 0} {$i < [llength $numbers]} {incr i 1} {
puts "i is $i"} 

The result from previous example resembles the following output, assuming there is only one server in the environment. If there is more than one server, it prints all of the server names:

i is 1
i is 3
i is 5
i is 7
i is 11
i is 13


break and continue

We can control loop execution with the break and continue commands.

The break command causes an immediate exit from a loop. The continue command causes the loop to continue with the next iteration.


catch

An error occurs if you call a command with the wrong number of arguments or if the command detects some error condition particular to its implementation. An uncaught error prevents a script from running. Use the catch command trap such errors. The catch command takes two arguments, for example:

The first argument is a command body. The second argument is the name of a variable containing the result of the command or an error message if the command raises an error. The catch command returns a value of zero if no error was caught or a value of one if the command catches an error. For example:

catch {expr 20 / 5} result ==> 0
puts $result
==> 4
catch {expr text / 5} result ==> 1
puts $result
==> syntax error in expression "text / 5"


return

Use the return command to return a value prior to the end of the procedure body or if a contrast value must be returned.


Namespaces

Jacl tracks named entities such as variables, in namespaces. The wsadmin tool also adds entries to the global namespace for the scripting objects, such as, the AdminApp object

When you run a proc command, a local namespace is created and initialized with the names and the values of the parameters in the proc command. Variables are held in the local namespace while you run the proc command. When you stop the proc command, the local namespace is erased. The local namespace of the proc command implements the semantics of the automatic variables in languages such as C and Java.

While variables in the global namespace are visible to the top-level code, they are not visible by default from within a proc command. To make them visible, declare the variables globally using the global command. For the variable names that you provide, the global command creates entries in the local namespace that point to the global namespace entries that actually define the variables.

If we use a scripting object provided by wsadmin in a proc, you must declare it globally prior to you using it, for example:

proc { ... } {
  global AdminConfig
  ... [$AdminConfig ...]}


Calling scripts using another script

Use the source command to call a Jacl script from another Jacl script. For example:

Create a script called test1.jacl.

source c:/temp/script/testProcedure.jacl
printName Cathy Smith

Create a script called testProcedure.jacl.

proc printName {first last} {
 puts "My name is $first $last"}

Pass the following path as a script argument.

You must use forward slashes (/) as your path separator. Backward slashes (\) do not work.


Redirection using the exec command

The following Jacl exec command for redirection does not work on Linux platforms:

The exec command of the Jacl scripting language does not fully support redirection therefore it might cause problems on some platforms.

Do not use redirection when using the exec command of the Jacl language. Instead, we can save the exec command for redirection in a variable and write it to a file, for example:

In some cases, we can also perform a redirection using shell and a .sh command redirection, not a redirection issued by Tcl.


Related concepts:

Use wsadmin scripting with Jython


Related


Access command assistance from the dmgr console
Get started with wsadmin scripting


Related information:

IBM Jacl to Jython Conversion Assistant


+

Search Tips   |   Advanced Search