我有一个测试脚本,它有很多命令并且会生成很多输出,我使用set -xor set -vand set -e,所以当发生错误时脚本会停止。但是,为了定位问题,我仍然很难找到执行停止的哪一行。有没有一种方法可以在每行执行之前输出脚本的行号?或者输出生成的命令展示前的行号set -x?或者任何可以处理我的脚本行位置问题的方法都会有很大帮助。谢谢。
5 回答
您提到您已经在使用-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]}(): }'
    在 Bash 中,$LINENO包含脚本当前执行的行号。
如果您需要知道调用函数的行号,请尝试$BASH_LINENO. 请注意,此变量是一个数组。
例如:
#!/bin/bash       
function log() {
    echo "LINENO: ${LINENO}"
    echo "BASH_LINENO: ${BASH_LINENO[*]}"
}
function foo() {
    log "$@"
}
foo "$@"
有关 Bash 变量的详细信息,请参见此处。
价值 $LINENO 的 PS4 是你所需要的,
例如以下脚本(myScript.sh):
       #!/bin/bash -xv
       PS4='${LINENO}: '
       echo "Hello"
       echo "World"
输出将是:
  ./myScript.sh
  +echo Hello
  3 : Hello
  +echo World
  4 : World
    没有 LINENO 的 shell 的解决方法
在一个相当复杂的脚本中,我不想看到所有的行号;相反,我想控制输出。
定义一个函数
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"
如果源文件中这一行的编号是 16。
这基本上回答了How to show line number when execution bash script for users of ash or other shells without LINENO.
还有什么要补充的吗?
当然。你为什么需要这个?你如何处理这个?你能用这个做什么?这种简单的方法真的足够或有用吗?你为什么要修补这个?
想知道更多?阅读有关调试的反思
简单(但功能强大)的解决方案:放置echo在您认为导致问题的代码周围,并echo逐行移动,直到消息不再出现在屏幕上 - 因为脚本之前因错误而停止。
更强大的解决方案:安装bashdbbash调试器,逐行调试脚本