曲径通幽论坛

 找回密码
 立即注册
搜索
查看: 6441|回复: 0
打印 上一主题 下一主题

脚本调试:-x 选项,$LINENO,$PS4,$FUNCNAME

[复制链接]

4918

主题

5880

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34395
跳转到指定楼层
楼主
发表于 2011-5-30 14:54:20 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
-x 是 set 命令中的一个选项,它用来进入跟踪方式,这样会显示出脚本执行每一条命令及其参数,它是脚本调试中的一个有用选项。它输出的被执行的命令行及参数前面会添加一个 "+" 号。实际上,这个 "+" 号就是内置变量 $PS4 的值,可以输出验证:
[beyes@localhost ~]$ echo $PS4
+
我们可以对 -x 选项,或者说是 $PS4 这个变量进行扩展,使调试功能得到增强。以调试下面一段代码为例:
[Bash shell] 纯文本查看 复制代码
#!/bin/bash

checkname()
{
        if [ "$USER" = "beyes" ];then
                return 0
        else
                return 1
        fi
}

checkuid() 
{
        if ["$UID" -eq 500 ]; then
                return 0
        else
                return 1
        fi
}

checkname
if [ "$?" -eq 0 ]; then
        echo "check name ok!"
else
        echo "check name failed"
fi

checkuid
if [ "$?" -eq 0 ]; then
        echo "check uid ok!"
        exit 0
else
        echo "check uid failed"
        exit 1
fi

调试这段脚本时,先使用普通的运行方式:
[beyes@localhost ~]$ sh sp4.sh
sp4.sh: line 7: syntax error near unexpected token `else'
sp4.sh: line 7: `    else'
第 7 行发生语法错误,这里的 if 漏掉了 then 语句,修正后再次运行:

[beyes@localhost ~]$ sh sp4.sh
check name ok!
sp4.sh: line 14: [500: command not found
check uid failed
第 14 行发出命令找不到的错误。这是怎么回事呢?用 set 命令的 -x 选项,再配合 $LINENO 和 $FUNCNAME 内置变量来跟踪这个问题。首先对 $SP4 变量进行设置:

[beyes@localhost ~]$ export PS4='+$LINENO: {${FUNCNAME[0]}} '

然后以带有 -x 选项的方式运行脚本:

[beyes@localhost ~]$ sh sp4.sh
check name ok!
sp4.sh: line 14: [500: command not found
check uid failed
[beyes@localhost ~]$ sh -x sp4.sh
+21: {} checkname
+5: {checkname} '[' beyes = beyes ']'
+6: {checkname} return 0
+22: {} '[' 0 -eq 0 ']'
+23: {} echo 'check name ok!'
check name ok!
+28: {} checkuid
+14: {checkuid} '[500' -eq 500 ']'
sp4.sh: line 14: [500: command not found
+17: {checkuid} return 1
+29: {} '[' 1 -eq 0 ']'
+33: {} echo 'check uid failed'
check uid failed
+34: {} exit 1

找到 14 行这里,原来 shell 将 [500 当成是一个命令了。比较脚本代码时可以看到第 14 行中左中括号和 $? 之间没有空格,所以脚本在展开时被写成 [500 ,这样就被 shell 当作一个整体进行解释,而一个整体在 shell 中是要被解释为命令的。所以在 [ 和 $? 之间加上一个空格即可解决这个错误。


$LINENO 表示脚本执行到的当前行,这和 C语言 中的内置宏 __LINE__ 是一个道理。

$FUNCTION 也是一个内置变量,它相当于 C语言 中的内置宏 __func__ 。但 $FUNCTION 它比 __func__ 更强大,它实际上是一个数组变量,如同堆栈一般,在栈底的是脚本的顶层"main",在栈顶的是当前所执行的函数,所以 $[FUNCTION[0]} 就是要显示出当前的执行函数。

所以使用 -x ,$LINENO 以及 $FUNCNAME 配合使用,可以在调试脚本时跟踪脚本的执行流程及轨迹。

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|曲径通幽 ( 琼ICP备11001422号-1|公安备案:46900502000207 )

GMT+8, 2025-5-4 13:10 , Processed in 0.084355 second(s), 23 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表