Shell 科恩希尔-集“-x";(调试)全局标记?

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

有没有一种方法可以全局设置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 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