在全球范围内设置“-x”(调试)标志?

时间:2021-11-17 00:29:21

Is there a way to set the debug mode(set -x) on a KornShell (ksh) script globally? Currently it seems I have do something like the following:

是否有一种方法可以将调试模式(set -x)设置为全局的KornShell (ksh)脚本?目前,我似乎做了如下的事情:

a(){
   set -x
   #commands
}

b(){
   set -x
   #more commands
}

set-x 
a
#commands
b

I would really like to only have to call the set-x command in one place.

我只需要在一个地方调用set-x命令。

Note: This is all in KSH88 on AIX.

注意:这都在AIX上的KSH88中。

Example:

例子:

#!/bin/ksh
set -x

a(){
   echo "This is A!"
}

b(){
   echo "This is B!"
}

a
echo "Outside"
b
dev2:/home/me-> ./testSetX
+ a
This is A!
+ echo Outside
Outside
+ b
This is B!
dev2:/home/me->

5 个解决方案

#1


7  

This is ksh88 on an HP-UX machine:

这是ksh88在HP-UX机器上:

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

It sure looks like that works fine. I validated that it also works with a "set -x" anywhere before the first function call.

看起来没问题。在第一个函数调用之前,我验证了它也适用于“set -x”。

I moved to an AIX system, and experienced the problem you described. When functions are defined as either function a { or a() { in AIX ksh88, the set -x doesn't appear to carry forward into the function-local scope. Switching to ksh93 on the same AIX box, functions declared using the new function a { syntax also don't carry the outer set -x into the inner scope. However, ksh93 behaves like POSIX sh (and ksh88 on other platforms) used to behave, carrying the set -x through to the function when the function is defined in the old a(){ method. This is probably due to the backwards compatability in ksh93, where it tries to emulate the old behavior when functions are defined the old way.

我迁移到AIX系统,并体验了您描述的问题。当函数被定义为AIX ksh88中的{或a(){或a()函数时,set -x似乎没有将其带入函数-局部范围。在同一个AIX框上切换到ksh93,使用新函数声明的函数也不会将外部集-x带进内部范围。然而,ksh93的行为就像POSIX sh(和其他平台上的ksh88)一样,在旧的a()方法中定义函数时,将set -x传递给函数。这可能是由于ksh93的向后兼容性,当函数定义旧的方式时,它试图模仿旧的行为。

Therefore, you might be able to temporarily switch the interpreter over to ksh93 for debugging purposes, and then switch back to ksh88 if you don't like having the longer arrays, associative arrays, floating point math, namespace support, and rougly 10x improvement in execution speed which ksh93 brings. ;) Because it looks like the answer is "no, you can't do that" with ksh88 on AIX. :(

因此,您可能可以临时将解释器切换到ksh93,以进行调试,然后切换回ksh88,如果您不喜欢拥有更长的数组、关联数组、浮点数、名称空间支持,以及ksh93带来的执行速度上的rougly 10x改进。,)因为看起来答案是“不,你不能这样做”,ksh88在AIX上。:(

#2


4  

Add it to your shebang line:

把它添加到你的shebang线:

#!/bin/ksh -x

Or set it at the top of your script:

或者把它设置在脚本的顶部:

#!/bin/ksh
set -x

Or start your script from the command line:

或者从命令行启动脚本:

ksh -x script_name

#3


4  

I tested a global set -x with ksh88 (on Solaris 10) and ksh93 (Fedora 17) and with both a global set -x command at the top of the script does not have function-local scope (i.e. it does not have any local effects).

我用ksh88(在Solaris 10上)和ksh93 (Fedora 17)测试了一个全局集-x,并且在脚本的顶部有一个全局集-x命令没有函数-局部作用域(也就是说它没有任何局部作用)。

As a workaround you can enable local command tracing for all functions in scope (after they are defined) and before they are called via typeset:

作为一种变通方法,您可以使本地命令跟踪在范围内的所有函数(在它们被定义之后)以及在它们被称为typeset之前:

$ cat test.ksh
PS4='$LINENO: '

set -x

function foo {
  print Hello
}

bar() {
  print World
}

typeset -ft `typeset +f` 

foo
bar

Output under ksh88 (Solaris 10):

$ ksh test.ksh 
13: typeset +f
13: typeset -ft bar foo
15: foo
1: print Hello
Hello
16: bar
1: print World
World

Typeset commented out

$ ksh test.ksh 
15: foo
Hello
16: bar
World

Output under ksh93 (Fedora 17):

$ ksh test.ksh
13: typeset +f
13: typeset -ft 'bar()' foo
15: foo
6: print Hello
Hello
16: bar
10: print World
World

Typeset commented out

$ ksh test.ksh
15: foo
Hello
16: bar
10: print World
World

Output under bash

typeset commented out and print substituted with echo:

typeset注释掉了,用echo代替了print:

$ bash test.ksh
15: foo
6: echo Hello
Hello
16: bar
10: echo World
World

(bash 4.2.39(1) on Fedora 17)

(bash 4.2.39(1) Fedora 17)

Same output under zsh 5.0.2 on Fedora 17.

在Fedora 17上zsh 5.0.2中同样的输出。

Conclusion

When using Ksh, only with ksh93 and the fnname() function definition syntax a global set -x also has local scope. The typeset -ft based workaround is a relatively light way to enable command tracing for all functions.

在使用Ksh时,只使用ksh93和fnname()函数定义语法,全局设置-x也有局部作用域。基于typeset -ft的workaround是一种相对轻松的方式,可以为所有功能启用命令跟踪功能。

In bash (and zsh) a global set -x works as expected, i.e. it also has local scope for all functions.

在bash(和zsh)中,全局集合-x按预期工作,也就是说,它也具有所有函数的局部范围。

Thus, when writing new scripts using bash instead of ksh might be the better alternative because of this.

因此,使用bash而不是ksh编写新的脚本可能是更好的选择。

As a side note: bash is probably even more portable than ksh88 - especially more portable than ksh93.

附带说明:bash可能比ksh88更便携,特别是比ksh93更便携。

#4


1  

Be aware that scoping is impacted between the two types of function declarations

请注意,在这两种类型的函数声明之间会影响范围。

a() { }

(){ }

vs.

vs。

function a { }

函数一个{ }

In particular, the typset under ksh doesn't work as you would expect in the former case. Found out while trying to debug a script with a recursive function. More here:

特别是,ksh下的类型不像您在前一种情况下所期望的那样工作。在尝试用递归函数调试脚本时发现。更多:

http://www.dartmouth.edu/~rc/classes/ksh/functions.html

http://www.dartmouth.edu/ rc / classes / ksh / functions.html

#5


1  

The behavior of "set -x" is a "peculiarity" of the AIX shell (not to say brain d...).

“set -x”的行为是AIX shell的“特性”(不是说brain d…)。

You asked for "a way to set the debug mode... globally". Here is what I do to achieve this:

您要求“一种设置调试模式的方法……”全球”。以下是我所做的:

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;

To enable tracing, set $set_x in the environment of your script to "set -x". To control this on a call-by-call basis, prefix the call with "set_x='set -x'". Because an environment variable is used, this method naturally works with nested calls.

要启用跟踪,可以在脚本的环境中设置$set_x以“设置-x”。要在call-by-call基础上对其进行控制,请在调用前加上“set_x='set -x'”。由于使用了环境变量,所以该方法自然地处理嵌套调用。

All those uses of "$set_x;" are a bit ugly, but it works with all shells, and the benefit usually outweighs the cost.

所有这些“$set_x”的使用都有些难看,但是它与所有shell一起工作,而且收益通常超过成本。

Another example of an AIX shell "peculiarity":

AIX shell的另一个“特性”示例:

set -e;
trap "echo trapped at file scope" EXIT;
f() { return 1; }
main() { f; }
main;

The above should print "trapped at file scope", but prints nothing.

上面应该打印“被困在文件范围内”,但没有打印出来。

#1


7  

This is ksh88 on an HP-UX machine:

这是ksh88在HP-UX机器上:

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

It sure looks like that works fine. I validated that it also works with a "set -x" anywhere before the first function call.

看起来没问题。在第一个函数调用之前,我验证了它也适用于“set -x”。

I moved to an AIX system, and experienced the problem you described. When functions are defined as either function a { or a() { in AIX ksh88, the set -x doesn't appear to carry forward into the function-local scope. Switching to ksh93 on the same AIX box, functions declared using the new function a { syntax also don't carry the outer set -x into the inner scope. However, ksh93 behaves like POSIX sh (and ksh88 on other platforms) used to behave, carrying the set -x through to the function when the function is defined in the old a(){ method. This is probably due to the backwards compatability in ksh93, where it tries to emulate the old behavior when functions are defined the old way.

我迁移到AIX系统,并体验了您描述的问题。当函数被定义为AIX ksh88中的{或a(){或a()函数时,set -x似乎没有将其带入函数-局部范围。在同一个AIX框上切换到ksh93,使用新函数声明的函数也不会将外部集-x带进内部范围。然而,ksh93的行为就像POSIX sh(和其他平台上的ksh88)一样,在旧的a()方法中定义函数时,将set -x传递给函数。这可能是由于ksh93的向后兼容性,当函数定义旧的方式时,它试图模仿旧的行为。

Therefore, you might be able to temporarily switch the interpreter over to ksh93 for debugging purposes, and then switch back to ksh88 if you don't like having the longer arrays, associative arrays, floating point math, namespace support, and rougly 10x improvement in execution speed which ksh93 brings. ;) Because it looks like the answer is "no, you can't do that" with ksh88 on AIX. :(

因此,您可能可以临时将解释器切换到ksh93,以进行调试,然后切换回ksh88,如果您不喜欢拥有更长的数组、关联数组、浮点数、名称空间支持,以及ksh93带来的执行速度上的rougly 10x改进。,)因为看起来答案是“不,你不能这样做”,ksh88在AIX上。:(

#2


4  

Add it to your shebang line:

把它添加到你的shebang线:

#!/bin/ksh -x

Or set it at the top of your script:

或者把它设置在脚本的顶部:

#!/bin/ksh
set -x

Or start your script from the command line:

或者从命令行启动脚本:

ksh -x script_name

#3


4  

I tested a global set -x with ksh88 (on Solaris 10) and ksh93 (Fedora 17) and with both a global set -x command at the top of the script does not have function-local scope (i.e. it does not have any local effects).

我用ksh88(在Solaris 10上)和ksh93 (Fedora 17)测试了一个全局集-x,并且在脚本的顶部有一个全局集-x命令没有函数-局部作用域(也就是说它没有任何局部作用)。

As a workaround you can enable local command tracing for all functions in scope (after they are defined) and before they are called via typeset:

作为一种变通方法,您可以使本地命令跟踪在范围内的所有函数(在它们被定义之后)以及在它们被称为typeset之前:

$ cat test.ksh
PS4='$LINENO: '

set -x

function foo {
  print Hello
}

bar() {
  print World
}

typeset -ft `typeset +f` 

foo
bar

Output under ksh88 (Solaris 10):

$ ksh test.ksh 
13: typeset +f
13: typeset -ft bar foo
15: foo
1: print Hello
Hello
16: bar
1: print World
World

Typeset commented out

$ ksh test.ksh 
15: foo
Hello
16: bar
World

Output under ksh93 (Fedora 17):

$ ksh test.ksh
13: typeset +f
13: typeset -ft 'bar()' foo
15: foo
6: print Hello
Hello
16: bar
10: print World
World

Typeset commented out

$ ksh test.ksh
15: foo
Hello
16: bar
10: print World
World

Output under bash

typeset commented out and print substituted with echo:

typeset注释掉了,用echo代替了print:

$ bash test.ksh
15: foo
6: echo Hello
Hello
16: bar
10: echo World
World

(bash 4.2.39(1) on Fedora 17)

(bash 4.2.39(1) Fedora 17)

Same output under zsh 5.0.2 on Fedora 17.

在Fedora 17上zsh 5.0.2中同样的输出。

Conclusion

When using Ksh, only with ksh93 and the fnname() function definition syntax a global set -x also has local scope. The typeset -ft based workaround is a relatively light way to enable command tracing for all functions.

在使用Ksh时,只使用ksh93和fnname()函数定义语法,全局设置-x也有局部作用域。基于typeset -ft的workaround是一种相对轻松的方式,可以为所有功能启用命令跟踪功能。

In bash (and zsh) a global set -x works as expected, i.e. it also has local scope for all functions.

在bash(和zsh)中,全局集合-x按预期工作,也就是说,它也具有所有函数的局部范围。

Thus, when writing new scripts using bash instead of ksh might be the better alternative because of this.

因此,使用bash而不是ksh编写新的脚本可能是更好的选择。

As a side note: bash is probably even more portable than ksh88 - especially more portable than ksh93.

附带说明:bash可能比ksh88更便携,特别是比ksh93更便携。

#4


1  

Be aware that scoping is impacted between the two types of function declarations

请注意,在这两种类型的函数声明之间会影响范围。

a() { }

(){ }

vs.

vs。

function a { }

函数一个{ }

In particular, the typset under ksh doesn't work as you would expect in the former case. Found out while trying to debug a script with a recursive function. More here:

特别是,ksh下的类型不像您在前一种情况下所期望的那样工作。在尝试用递归函数调试脚本时发现。更多:

http://www.dartmouth.edu/~rc/classes/ksh/functions.html

http://www.dartmouth.edu/ rc / classes / ksh / functions.html

#5


1  

The behavior of "set -x" is a "peculiarity" of the AIX shell (not to say brain d...).

“set -x”的行为是AIX shell的“特性”(不是说brain d…)。

You asked for "a way to set the debug mode... globally". Here is what I do to achieve this:

您要求“一种设置调试模式的方法……”全球”。以下是我所做的:

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;

To enable tracing, set $set_x in the environment of your script to "set -x". To control this on a call-by-call basis, prefix the call with "set_x='set -x'". Because an environment variable is used, this method naturally works with nested calls.

要启用跟踪,可以在脚本的环境中设置$set_x以“设置-x”。要在call-by-call基础上对其进行控制,请在调用前加上“set_x='set -x'”。由于使用了环境变量,所以该方法自然地处理嵌套调用。

All those uses of "$set_x;" are a bit ugly, but it works with all shells, and the benefit usually outweighs the cost.

所有这些“$set_x”的使用都有些难看,但是它与所有shell一起工作,而且收益通常超过成本。

Another example of an AIX shell "peculiarity":

AIX shell的另一个“特性”示例:

set -e;
trap "echo trapped at file scope" EXIT;
f() { return 1; }
main() { f; }
main;

The above should print "trapped at file scope", but prints nothing.

上面应该打印“被困在文件范围内”,但没有打印出来。