KornShell - 设置“-x” (调试)全局标记?

发布于 2024-08-21 06:47:26 字数 646 浏览 14 评论 0原文

有没有办法设置调试模式(set -x) 在全局 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
This is A!
+ echo Outside
Outside
+ b
This is B!
dev2:/home/me->

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:

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.

Note: This is all in KSH88 on AIX.

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->

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

沉睡月亮 2024-08-28 06:47:26

这是 HP-UX 机器上的 ksh88:

me@host ..dev/
$ cat ./test/verbose
#!/bin/ksh
set -x

hello() {
  print $1
}

hello kapow!
exit

[email protected]/
$ ./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,如果您不喜欢更长的数组、关联数组、浮点数学、命名空间支持以及大约 10 倍的性能改进,则可以切换回 ksh88。 ksh93带来的执行速度。 ;) 因为对于 AIX 上的 ksh88 来说,答案似乎是“不,你不能这样做”。 :(

This is ksh88 on an HP-UX machine:

me@host ..dev/
$ cat ./test/verbose
#!/bin/ksh
set -x

hello() {
  print $1
}

hello kapow!
exit

[email protected]/
$ ./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.

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.

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. :(

り繁华旳梦境 2024-08-28 06:47:26

我使用 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) 下的输出:

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

Typeset 注释掉

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

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 注释掉

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

bash

typeset 下的输出被注释掉并用 echo 替换 print:

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

(Fedora 17 上的 bash 4.2.39(1))

zsh 5.0 下的相同输出Fedora 17 上的 .2。

结论

使用 Ksh 时,仅使用 ksh93 和 fnname() 函数定义语法,全局 set -x 也具有本地作用域。基于 typeset -ft 的解决方法是为所有函数启用命令跟踪的相对简单的方法。

在 bash(和 zsh)中,全局 set -x 按预期工作,即它还具有所有函数的本地作用域。

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

附带说明一下:bash 可能比 ksh88 更便携——尤其是比 ksh93 更便携。

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).

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:

$ 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:

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

(bash 4.2.39(1) on Fedora 17)

Same output under zsh 5.0.2 on Fedora 17.

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.

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

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

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

不念旧人 2024-08-28 06:47:26

将其添加到您的 shebang 行:

#!/bin/ksh -x

或将其设置在脚本的顶部:

#!/bin/ksh
set -x

或从命令行启动脚本:

ksh -x script_name

Add it to your shebang line:

#!/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
罪#恶を代价 2024-08-28 06:47:26

“set -x”的行为是 AIX shell 的“特殊性”(更不用说 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_x='set -x'”前缀。
由于使用了环境变量,因此该方法自然适用于嵌套调用。

所有这些“$set_x;”的用法都有点难看,但它适用于所有 shell,
并且收益通常大于成本。

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

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

上面应该打印“trapped at file scope”,但什么也不打印。

The behavior of "set -x" is a "peculiarity" of the AIX shell (not to say 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.

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

Another example of an AIX shell "peculiarity":

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.

清音悠歌 2024-08-28 06:47:26

请注意,两种类型的函数声明之间的作用域受到影响

a() {
}

function a {
}

特别是,ksh 下的类型集无法按照您在前一种情况下所期望的方式工作。在尝试使用递归函数调试脚本时发现的。更多信息请参见:

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

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

a() {
}

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:

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文