我有一个测试脚本,其中包含许多命令并且会生成大量输出,我使用set -x
或set -v
和set -e
,因此脚本在发生错误时会停止。但是,对于我来说仍然很难找到执行停止的哪一行以便定位问题。
是否有一种方法可以在每个命令执行之前输出脚本的行号?
或者在由set -x
生成的命令展示之前输出行号?
或者任何可以解决我的脚本行位置问题的方法都将是一个很好的帮助。
谢谢。
你提到你已经在使用 -x
。变量PS4
表示该值是在设置-x
选项时打印在命令行之前的提示符,默认为冒号后跟空格:
。
您可以更改PS4
以发出LINENO
(当前正在执行的脚本或shell函数中的行号)。
例如,如果您的脚本读取:
$ cat script
foo=10
echo ${foo}
echo $((2 + 2))
这样执行会打印行号:
$ PS4='Line ${LINENO}: ' bash -x script
Line 1: foo=10
Line 2: echo 10
10
Line 3: echo 4
4
http://wiki.bash-hackers.org/scripting/debuggingtips 给出了最终的PS4
命令,这个命令会输出您可能需要跟踪的所有内容:
export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
$LINENO
包含当前正在执行的脚本所在的行号。$BASH_LINENO
。请注意,此变量是一个数组。#!/bin/bash
function log() {
echo "LINENO: ${LINENO}"
echo "BASH_LINENO: ${BASH_LINENO[*]}"
}
function foo() {
log "$@"
}
foo "$@"
有关Bash变量的详细信息,请在此处查看。
PS4的值为$LINENO,这是您所需的。
例如,以下脚本(myScript.sh):
#!/bin/bash -xv
PS4='${LINENO}: '
echo "Hello"
echo "World"
输出将是:
./myScript.sh
+echo Hello
3 : Hello
+echo World
4 : World
在一个相当复杂的脚本中,我不想看到所有的行号;相反,我希望能够控制输出。
定义一个函数:
echo_line_no () {
grep -n "$1" $0 | sed "s/echo_line_no//"
# grep the line(s) containing input $1 with line numbers
# replace the function name with nothing
} # echo_line_no
像这样用引号包含起来
echo_line_no "this is a simple comment with a line number"
输出为
16 "this is a simple comment with a line number"
LINENO
的ash或其他shell用户的如何在执行bash脚本时显示行号的问题。简单(但强大)的解决方案:在你认为引起问题的代码周围放置echo
,并逐行移动echo
直到屏幕上不再出现消息 - 因为脚本已经因错误而停止。
更加强大的解决方案:安装bashdb
bash调试器,并逐行调试脚本。
echo "foo" >&2
- hek2mgl如果您在函数中使用$LINENO
,它将缓存第一次出现的行号。相反,请使用${BASH_LINENO[0]}
echo
要好得多。 - Suvarna Pattayil-x
应该打印行号,或者说-nx
应该包括行号。对我来说,这是一个“什么鬼”的时刻... - jww\033[0;33m+(${BASH_SOURCE}:${LINENO}):\033[0m ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
翻译为:一些颜色的\033[0;33m+(${BASH_SOURCE}:${LINENO}):\033[0m ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
- Ulysse BN