将 wsadmin 脚本编制与 Jacl 配合使用(不推荐)
Jacl 是 TCL 的备用实现,完全以 Java™ 代码编写。
wsadmin 工具使用 Jacl V1.3.2。
Jacl 语法在 wsadmin 工具中的稳定性
Jacl 语言已稳定用于该产品的 V7 版本。 IBM® 目前不打算在产品的后续发行版中废弃或移除此功能; 但未来的投资将集中在 Jython 语言上,这是战略性的替代方法。 无需更改现有的使用 Jacl 的任何应用程序及脚本;但是对于新的应用程序,您应该考虑选择使用较稳定的语言。
- 管理控制台命令辅助 - 管理控制台的一个功能部件,显示与控制台交互的用户所执行的操作的等价 wsadmin 命令。 控制台命令辅助功能部件的输出可直接传输到 WebSphere Application Server Tool ,这将简化基于管理控制台操作的 Jython 脚本的开发。 还可以在使用控制台命令辅助功能部件之后将输出保存在纯文本文件中,以供将来使用。
- Jacl 到 Jython 转换实用程序 - 将 Jacl 语法的 wsadmin 脚本转换为等价的 Jython 语法的 wsadmin 脚本。 许多新的 wsadmin 高级命令,它们通过使用简单的参数和灵活的缺省逻辑来从底层管理模型中对脚本进行解耦。
基本语法
Jacl 命令的基本语法如下:
Command arg1 arg2 arg3 ...
命令可以是一个内置命令名,也可以是一个 Jacl 过程。 例如:
puts stdout {Hello, world!}
=> Hello, world!
在此示例中,命令是 puts,它有两个参数、一个 I/O 流标识和一个字符串。 puts 命令将字符串与尾随的新行字符一起写入 I/O 流。 参数由命令解释。 在该示例中,stdout 用于标识标准输出流。 将 stdout 用作名称是由 puts 命令和其他 I/O 命令使用的约定。 stderr 识别标准错误输出,而 stdin 识别标准输入。
变量
set 命令将值指定给变量。 此命令有两个参数:变量的名称和值。 变量名可以是任何长度,且区分大小写。 在使用 Jacl 变量之前无须声明这些 Jacl 变量。 解释器将在第一次指定值时创建变量。 例如:
set a 5
=> 5
set b $a
=> 5
第二个示例将变量 a 的值指定给变量 b。 使用美元符号 ($) 表明变量替换。 您可以使用 unset 命令删除变量,例如:
unset varName1 varName2 ...
您可以将任何数量的变量传递到 unset 命令。 如果尚未定义变量,那么 unset 命令将产生错误。 您可以使用 unset 命令删除整个数组或只删除单个数组元素。 在数组上使用 unset 命令是清除大数据结构的简便方式。 可以用 info exists 命令测试变量是否存在。 因为 incr 参数首先要求变量存在,所以可能需要测试变量是否存在,例如:
if ![info exists my_info] {set my_info 0} else {incr my_info}
命令替换
替换的第二种格式是命令替换。 嵌套命令由方括号 [ ]定界。 Jacl 解释器对方括号中的所有内容求值,并将其作为一条命令求值。 例如:
set len [string length my_string]
=> 6
在此示例中,嵌套命令如下所示: string length
my_string。 string 命令对字符串执行各种操作。 在这种情况下,命令要求字符串 my_string 的长度。 单个命令中有几种命令替换情况,解释器从左括号至右括号处理它们。 例如:
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
数学表达式
Jacl 解释器不对数学表达式求值。 使用 expr 命令对数学表达式求值。 expr 命令的实现采用所有参数,将它们并置到一个字符串中,并将该字符串作为数学表达式进行语法分析。 expr 命令在计算答案之后,会将答案格式化为字符串并返回。 例如:
expr 7.2 / 3
=> 2.4
反斜杠替换
Jacl 解释器执行的最后一个替换类型是反斜杠替换。 使用反斜杠来添加对于解释器有特殊含义的引号字符。 例如,如果要指定美元标记、花括号或括号字符,您可以用反斜杠来对它进行引用。 如果您正在使用许多反斜杠,那么您可以代之以使用花括号将内容分组,以关闭特殊字符的所有解释。 有几种必需反斜杠的情况。 例如:
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 {$ {} [] { [ } ]}
=> $ {} [] { [ } ]
您还可以使用反斜杠将长命令在多个行上继续。 没有反斜杠的新行将终止命令。 行末的反斜杠字符会转换为空格。 例如:
set totalLength [expr [string length "first string"] + \
[string length "second string"]]
=> 25
使用花括号和双引号分组
使用双引号和花括号将词语分组在一起。 使用引号可以在组中进行替换,而使用花括号将阻止进行替换。 此规则适用于命令、变量和反斜杠替换。 例如:
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].
在第二个示例中,Jacl 解释器从 puts 命令在第二个参数上执行变量和命令替换。 在第三个命令中阻止替换,因此字符串按原样打印。
因为 Jacl 语言使用反斜杠字符 (\) 作为转义字符,所以还必须特别注意路径描述。 要修正此问题,可在分布式路径语句中用正斜杠来替换每个反斜杠,或使用两个反斜杠。 例如:
C:/ 或 C:\\
过程和作用域
Jacl 使用 proc 命令定义过程。 定义过程的基本语法如下:
proc name arglist body
第一个参数是正在定义的过程的名称。 该名称是区分大小写的,实际上它可以包含任何字符。 过程名称和变量名不会相互冲突。 第二个参数是过程的参数列表。 第三个参数是条命令,或更通常是形成过程主体的一组命令。 一旦定义 Jacl 过程,它将与任何内置命令一样使用。 例如:
proc divide {x y} {
set result [expr $x/$y]
puts $result
}
在脚本中,以下说明的是如何调用 divide 过程:
divide 20 5
它将返回与以下内容相似的结果:
4
在此示例中不需要使用变量 c。 还可以将该过程主体编写为:
return [expr sqrt($a * $a + $b * $b)]
此示例中的 return 命令是可选的,因为 Jacl 解释器将主体中最后一条命令值作为过程值返回。 因此,可以将该过程主体精简为:
expr sqrt($a * $a + $b * $b)
该过程结果是主体中最后一条命令返回的结果。 return 命令可用于返回特定值。
过程名称中存在单个、全局作用域。 您可以在另一个过程中定义过程,但是在任何位置都可以看到它。 变量和过程有不同的名称空间,因此,过程和变量可以具有相同名称而不会发生冲突。 每个过程都有变量的本地作用域。 过程中引入的变量只有在过程调用期间才存在。 过程返回之后,会取消定义这些变量。 如果外部作用域中存在同一变量名,那么使用过程中的变量名不会对它产生影响。 过程外部定义的变量对于过程不可视,除非使用了全局作用域命令。
全局作用域是顶级作用域。 此作用域在任何过程外。 必须通过使用 global 命令使变量在可以访问过程中命令的全局作用域中定义。 global 命令的语法如下:
global varName1 varName2 ...
意见
使用井号字符 (#) 进行注释。
命令行参数
Jacl shell 将命令行参数作为 argv 变量的值传递到脚本。 命令行参数的数目由 argc 变量提供。 程序或脚本的名称不是 argv 的一部分,也不会由 argc 计数。 argv 变量是个列表。 使用 lindex 命令从参数列表抽取项,例如:
set first [lindex $argv 0]
set second [lindex $argv 1]
字符串和模式匹配
字符串是 Jacl 语言中的基本数据项。 您有多条命令可用于处理字符串。 string 命令的一般语法如下:
string operation stringvalue otherargs
operation 参数确定字符串的操作。 第二个参数是字符串值。 根据所执行的操作,可能还存在其他参数。
下表包含 string 命令的摘要:
| 命令 | 描述 |
|---|---|
| string compare str1 str2 | 按字典顺序比较字符串。 如果相等,那么返回 0;如果 str1 排在 str2 前面,那么返回 -1;其他情况则返回 1。 |
| string first str1 str2 | 返回 str1 第一次出现在 str2 中的索引,如果未找到 str1,那么返回 -1。 |
| string index string1 index1 | 返回指定索引的字符。 |
| string last str1 str2 | 返回 str1 最后一次出现在 str2 中的索引,如果未找到 str1,那么返回 -1。 |
| string length string | 返回字符串中的字符数。 |
| string match pattern str | 如果 str 匹配模式,那么返回 1,否则返回 0。 |
| string range str i j | 返回从 i 到 j 的 str 的字符范围 |
| string tolower string | 以小写字母形式返回字符串。 |
| string toupper string | 以大写字母形式返回字符串。 |
| string trim string ?chars? | 从字符串两端修剪 chars 中的字符。 chars 缺省为空格。 |
| string trimleft string ?chars? | 从字符串开头修剪 chars 中的字符。 chars 缺省为空格。 |
| string trimright string ?chars? | 从字符串末尾修剪 chars 中的字符。 chars 缺省为空格。 |
| string wordend str ix | 返回字符的 str 中的索引,该字符在包含索引 ix 的字符的字后。 |
| string wordstart str ix | 返回第一个字符的 str 中的索引,该字符在包含索引 ix 的字符的字中。 |
append 命令
append 命令的第一个参数是变量名。 它将剩余的参数并置到命名变量的当前值。 例如:
set my_item z
=> z
append my_item a b c
=> zabc
regexp 命令
regexp 命令提供对正则表达式匹配器的直接访问。 语法如下:
regexp ?flags? pattern string ?match sub1 sub2 ...?
如果字符串的一部分与模式匹配,那么返回值是 1。 否则,返回值为 0。 模式不必匹配整个字符串。 如果您需要更多控制,那么可以将 ^ 放在模式开头,从而将模式固定到字符串开头,或者可以将美元标记 $ 放在模式末尾,从而将模式固定在字符串末尾。 您可以通过使用这两个字符强制模式匹配整个字符串。 例如:
set text1 "This is the first string"
=> This is the first string
regexp "first string" $text1
=> 1
regexp "second string" $text1
=> 0
Jacl 数据结构
Jacl 语言中的基本数据结构是字符串。 其中存在两种更高级别的数据结构:列表和数组。 列表作为字符串来实现,而结构由字符串的语法定义。 语法规则与命令相同。 命令是列表的特殊实例。 数组是有索引的变量。 索引是字符串值,因此您可以将数组看作是从一个字符串(索引)到另一个字符串(数组元素值)的映射。
Jacl 列表
Jacl 语言的列表是有特殊解释的字符串。 在 Jacl 语言中,列表与命令有同一结构。 列表是一个以空格分隔的列表元素的字符串。 可以使用花括号或引号将具有空格的单词分组到单个列表元素中。
下表包含有关列表的命令:
| 命令 | 描述 |
|---|---|
| list arg1 arg2 | 用列表的所有参数来创建它。 |
| lindex list i | 返回列表的第 i 个元素。 |
| llength list | 返回列表中的元素数。 |
| lrange list i j | 返回列表的第 i 到第 j 个元素。 |
| lappend listVar arg arg ... | 将元素追加到 listVar 的值 |
| linsert list index arg arg ... | 将元素插入到列表中位置索引处的元素前面。 返回一个新的列表。 |
| lreplace list i j arg arg ... | 用 args 替换列表中的元素 i 到 j。 返回一个新的列表。 |
| lsearch mode list value | 返回根据方式匹配值的列表中元素的索引,分别是 -exact、-glob 或 -regexp,-glob 是缺省值。 如果未找到,那么返回 -1。 |
| lsort switches list | 根据以下开关符对列表的元素进行排序:-ascii、-integer、-real、-increasing、-decreasing、-command 命令。 返回一个新的列表。 |
| concat arg arg arg ... | 将多个列表连接起来,成为一个列表。 |
| join list joinString | 通过用 joinString 分隔列表中的元素,从而将它们合并起来。 |
| split string splitChars | 将字符串完全分割为列表元素,使用 splitChars 中的字符作为列表元素间的边界。 |
数组
set arr(index) value替换美元标记 ($) 以包含数组元素的值,例如:
set my_item $arr(index)
例如:
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
下表包含数组命令:
| 命令 | 描述 |
|---|---|
| array exists arr | 如果 arr 是数组变量,那么返回 1。 |
| array get arr | 返回以索引和相应的数组值交替出现的列表。 |
| array names arr ?pattern? | 返回为 arr 定义的所有索引或者与字符串匹配模式相匹配的索引的列表。 |
| array set arr list | 初始化列表中的 arr 数组,该列表需要与 get 返回的列表具有相同格式。 |
| array size arr | 返回为 arr 定义的索引数。 |
| array startsearch arr | 返回搜索整个 arr 的搜索令牌。 |
| array nextelement arr id | 在由令牌标识识别的搜索中,返回数组中下一个元素的值。 如果搜索中不再有元素,那么返回空字符串。 |
| array anymore arr id | 如果搜索中还有元素,那么返回 1。 |
| array donesearch arr id | 结束由 id 识别的搜索。 |
控制流命令
存在以下循环命令:
whileforeachfor
以下是条件命令:
ifswitch
以下是错误处理命令:
catch
以下命令微调控制流:
breakcontinuereturnerror
if then else
if 命令是基本条件命令。 它说明:如果表达式为真,那么返回第二个代码行,否则运行另一代码行。 第二个命令主体(else 子句)是可选的。 命令语法如下:
if boolean then body1 else body2
then 和 else 关键字是可选的。 例如:
if {$x == 0} {
puts stderr "Divide by zero!"
} else {
set slope [expr $y/$x]
}
switch
根据表达式的值,使用 switch 命令分支到多条命令中的某条命令。 您可以基于模式匹配和简单比较来进行选择。 可以指定任何数量的模式-主体对。 如果多个模式匹配,那么只对第一个匹配模式的代码主体求值。 该命令的一般格式如下:
switch flags value pat1 body1 pat2 body2 ...
您还可以将所有模式-主体对分组到一个参数中:
switch flags value {pat1 body1 pat2 body2 ...}
有四个可能的标志用来确定值如何匹配。
-exact将值与其中一个模式完全匹配。-glob使用通配符样式模式匹配。-regexp使用正则表达式模式匹配。--没有标志(或标志结束)。 当值可以用虚线 (-) 开头时有用。
例如:
switch -exact -- $value {
foo {doFoo; incr count(foo)}
bar {doBar; return $count(foo)}
default {incr count(other)}
}
如果与上一个主体关联的模式是 default,那么没有其他模式匹配时启动该命令主体。 default 关键字仅对上一个“模式/主体”对起作用。 如果对先前的主体使用缺省模式,那么会将它视为与文字串缺省值进行匹配的模式。
foreach
foreach 命令循环整个命令主体,并将循环变量指定给列表中的每个值。 语法如下:
foreach loopVar valueList commandBody
第一个参数是变量名。 命令主体对循环中的每个元素运行一次,且循环变量有列表中的连续值。 例如:
set numbers {1 3 5 7 11 13}
foreach num $numbers {
puts $num
}
假定环境中只存在一台服务器,那么前一个示例的结果将为以下输出。 如果存在多台服务器,那么返回所有服务器的信息:
1
3
5
7
11
13
while
while 命令采用两个参数;测试和命令主体,例如:
while booleanExpr body
如果表达式的值为 true(非零),那么 while 命令将反复测试布尔表达式并运行主体。 例如:
set i 0
while {$i < 5} {
puts "i is $i"
incr i}
假定只有一台服务器,那么前一个示例的结果类似于以下输出。 如果有多台服务器,那么它将列示所有服务器:
i is 0
i is 1
i is 2
i is 3
i is 4
针对
for 命令类似于 C 语言的 for 语句。 它采用四个参数,例如:
for initial test final body
第一个参数是初始化循环的命令。 第二个参数是用于确定循环主体是否运行的布尔表达式。 第三个参数是在循环主体后运行的命令,例如:
set numbers {1 3 5 7 11 13}
for {set i 0} {$i < [llength $numbers]} {incr i 1} {
puts "i is $i"
}
假定环境中只有一台服务器,那么前一个示例的结果类似于以下输出。 如果有多台服务器,那么它将列示所有服务器名称:
i is 1
i is 3
i is 5
i is 7
i is 11
i is 13
break 和 continue
您可以使用 break 和 continue 命令控制循环执行。 break 命令会导致立即从循环中退出。 continue 命令会导致循环继续执行下一个迭代。
捕获
如果使用错误的参数数目调用命令,或者命令检测到特定于其实现的某些错误条件,那么将产生错误。 未获取的错误会阻止脚本运行。 使用 catch 命令获取这种错误。 catch 命令采用两个参数,例如:
catch command ?resultVar?
第一个参数是命令主体。 第二个参数是变量的名称,它包含命令结果或错误消息(如果命令产生错误)。 如果没有获取错误,那么 catch 命令返回值 0,如果该命令获取了错误,那么返回值 1。 例如:
catch {expr 20 / 5} result
==> 0
puts $result
==> 4
catch {expr text / 5} result
==> 1
puts $result
==> syntax error in expression "text / 5"
返回
在过程主体结束前之前或者在必须返回对比值时,请使用 return 命令来返回值。
名称空间
Jacl 将跟踪名称空间中所指定的实体(例如,变量)。 wsadmin 工具还将条目添加到脚本编制对象(例如,AdminApp 对象)的全局名称空间。
当您运行 proc 命令时,会使用 proc 命令中的参数名称和参数值来创建和初始化本地名称空间。 当您运行 proc 命令时,变量保存在本地名称空间中。 当您停止 proc 命令时,将擦除本地名称空间。 proc 命令的本地名称空间以 C 和 Java 之类的语言实现自动变量的语义。
当全局名称空间中的变量对于顶层代码可视时,缺省情况下它们在 proc 命令中不可视。 要使它们可视,请使用 global 命令全局声明这些变量。 对于您提供的变量名,全局命令在本地名称空间中创建条目,它们指向实际定义这些变量的全局名称空间条目。
如果您在 proc 中使用 wsadmin 工具所提供的脚本编制对象,那么在使用该对象之前必须对其进行全局声明,例如:
proc { ... } {
global AdminConfig
... [$AdminConfig ...]
}
使用一个脚本调用其他脚本
请使用 source 命令来从一个 Jacl 脚本调用另一个 Jacl 脚本。 例如:
创建称为 test1.jacl 的脚本。
source c:/temp/script/testProcedure.jacl
printName Cathy Smith
source /temp/script/testProcedure.jacl
printName Cathy Smith
创建称为 testProcedure.jacl 的脚本。
proc printName {first last} {
puts "My name is $first $last"
}
请将以下路径作为脚本参数进行传递。
wsadmin -lang jacl -f c:/temp/script/test1.jacl
wsadmin -lang jacl -f '/temp/script/test1.jacl'
必须将正斜杠 (/) 用作路径分隔符。 反斜杠 (\) 不起作用。
使用 exec 命令重定向
以下用于重定向的 Jacl exec 命令在 Linux® 平台上不起作用:
eval exec ls -l > /tmp/out
Jacl 脚本编制语言的 exec 命令不完全支持重定向,因此该命令在某些平台上可能会产生问题。
使用 Jacl 语言的 exec 命令时,不要使用重定向。 相反,可以将用于重定向的 exec 命令保存在一个变量中,然后将该变量写入文件,例如:
open /tmp/out w puts $fileId $result close $fileId
在某些情况下,还可以使用 shell 和 .sh 命令重定向(而不是 Tcl 发出的重定向)来执行重定向。