Shell 科恩希尔-集“-x";(调试)全局标记?
有没有一种方法可以全局设置KornShell(ksh)脚本的调试模式()?目前,我似乎做了如下工作:Shell 科恩希尔-集“-x";(调试)全局标记?,shell,debugging,scripting,ksh,script-debugging,Shell,Debugging,Scripting,Ksh,Script Debugging,有没有一种方法可以全局设置KornShell(ksh)脚本的调试模式()?目前,我似乎做了如下工作: a(){ set -x #commands } b(){ set -x #more commands } set-x a #commands b 我只想在一个地方调用set-x命令 注意:这些都在AIX上的KSH88中 例如: #!/bin/ksh set -x a(){ echo "This is A!" } b(){ echo "This is
a(){
set -x
#commands
}
b(){
set -x
#more commands
}
set-x
a
#commands
b
我只想在一个地方调用set-x命令
注意:这些都在AIX上的KSH88中
例如:
#!/bin/ksh
set -x
a(){
echo "This is A!"
}
b(){
echo "This is B!"
}
a
echo "Outside"
b
dev2:/home/me->./testSetX
+a
这是一个好主意!
+呼应
外面
+b
这是B!
dev2:/home/me->
将其添加到您的shebang行:
#!/bin/ksh -x
或者将其设置在脚本的顶部:
#!/bin/ksh
set -x
或者从命令行启动脚本:
ksh -x script_name
这是HP-UX机器上的ksh88:
me@host ..dev/
$ cat ./test/verbose
#!/bin/ksh
set -x
hello() {
print $1
}
hello kapow!
exit
me@host..dev/
$ ./test/verbose
+ hello kapow!
+ print kapow!
kapow!
+ exit
看起来效果不错。我验证了它在第一次函数调用之前的任何地方都可以使用“set-x”
我转到了AIX系统,遇到了您描述的问题。在AIX ksh88中将函数定义为function a{
或a(){
时,set-x
似乎不会转入函数本地范围。在同一AIX框上切换到ksh93时,使用新的function a声明函数{
语法也不会将外部的set-x
带入内部作用域。但是,ksh93的行为类似于POSIX sh(以及其他平台上的ksh88),在旧的a()中定义函数时,将set-x
传递给函数{
方法。这可能是由于ksh93中的向后兼容性,当函数以旧的方式定义时,它尝试模拟旧的行为
因此,出于调试目的,您可以暂时将解释器切换到ksh93,如果您不喜欢ksh93所带来的更长的数组、关联数组、浮点数学、命名空间支持和执行速度的10倍提高,那么您可以切换回ksh88,因为答案似乎是肯定的在AIX上使用ksh88时,“不,您不能这样做”。(请注意,两种类型的函数声明之间的作用域会受到影响 (){ } vs 功能a{ } 特别是,在前一种情况下,ksh下的类型集无法正常工作。在尝试使用递归函数调试脚本时发现。详细信息如下: set-x的行为是aixshell的一个“特性”(更不用说brain d…) 您要求提供“全局设置调试模式的方法”。 以下是我为实现这一目标所做的:
set_x="${set_x-:}"; # Defaults to ":" (NOOP) unless already non-empty
# Using ":" instead of "" makes termination via semicolon work,
# which in turn allows inlining, especially when using SSH.
# Alternatively, if tracing should be on by default:
#set_x="${set_x-set -x}"; # Defaults to "set -x" unless already non-empty
$set_x; # Apply to file scope
f() {
$set_x; # Apply to local scope
echo working...;
}
main() {
$set_x; # Apply to local scope
f;
ssh localhost $set_x\; hostname; # Apply to remote shell scope
ssh localhost "set_x=\"$set_x\" foo"; # Apply to foo called in remote shell
}
main;
要启用跟踪,请将脚本环境中的$set_x
设置为“set-x
”。
要逐个调用进行控制,请在调用前加上“set\u x='set-x'
”。
由于使用了环境变量,因此此方法自然适用于嵌套调用
“$set_x;
”的所有这些用法都有点难看,但它适用于所有shell,
而且收益通常大于成本
AIX shell“特性”的另一个示例:
上面应该打印“被困在文件范围内”,但不打印任何内容。我用ksh88(在Solaris 10上)和ksh93(Fedora 17上)测试了一个全局
set-x
,并且脚本顶部的全局set-x
命令没有函数局部范围(即,它没有任何局部效果)
作为一种解决方法,您可以为作用域中的所有函数启用本地命令跟踪(在定义它们之后),并在通过typeset
调用它们之前:
$ cat test.ksh
PS4='$LINENO: '
set -x
function foo {
print Hello
}
bar() {
print World
}
typeset -ft `typeset +f`
foo
bar
ksh88(Solaris 10)下的输出:
排版
ksh93(Fedora 17)下的产量:
排版
bash下的输出
排版
注释掉并用echo替换打印
:
$ bash test.ksh
15: foo
6: echo Hello
Hello
16: bar
10: echo World
World
(bash 4.2.39(1)关于Fedora 17)
在Fedora 17上的zsh 5.0.2下输出相同
结论
当使用Ksh时,只有使用ksh93和函数定义语法时,全局set-x
也有局部作用域。基于typeset-ft
的变通方法是对所有函数启用命令跟踪的相对较轻的方法
在bash(和zsh)中,全局set-x
按预期工作,也就是说,它对所有函数都有局部作用域
因此,在编写新脚本时,使用bash而不是ksh可能是更好的选择
附带说明:bash可能比ksh88更具可移植性,尤其是比ksh93更具可移植性。不幸的是,这些对我来说都不起作用。我只看到了方法的名称。可能是因为我在使用ksh88。这很奇怪。我也只是在ksh88(和ksh93)中尝试过它在我的一个AIX系统上,我确实得到了所描述的behvior。但是我的HP-UX系统上的ksh88工作正常。我修改了我的答案以反映结果。仅供参考,Solaris 10上的ksh88
/usr/bin/ksh
也显示了所描述的行为(无全局影响set-x
)。感谢您的出色研究,我将了解如何升级到ksh93,但在我的环境中…IBM在同一个包中提供了ksh93和ksh88(至少在我所了解的AIX 5.3和6.1系统上是这样);二进制文件名为ksh93。如果有帮助的话…)+1这对我在AIX5.3和7.1上使用ksh88很有效。如果有更多关于排版工作原理的解释,那就太好了。
$ cat test.ksh
PS4='$LINENO: '
set -x
function foo {
print Hello
}
bar() {
print World
}
typeset -ft `typeset +f`
foo
bar
$ ksh test.ksh
13: typeset +f
13: typeset -ft bar foo
15: foo
1: print Hello
Hello
16: bar
1: print World
World
$ ksh test.ksh
15: foo
Hello
16: bar
World
$ ksh test.ksh
13: typeset +f
13: typeset -ft 'bar()' foo
15: foo
6: print Hello
Hello
16: bar
10: print World
World
$ ksh test.ksh
15: foo
Hello
16: bar
10: print World
World
$ bash test.ksh
15: foo
6: echo Hello
Hello
16: bar
10: echo World
World