gpt4 book ai didi

bash - 如何获取失败的 Bash 命令的实际行号?

转载 作者:行者123 更新时间:2023-11-29 08:54:29 29 4
gpt4 key购买 nike

在想出一种方法来捕获我的 Bash 脚本中的错误的过程中,我一直在试验“set -e”、“set -E”和“trap”命令。在此过程中,我发现了一些关于如何在函数上下文中评估 $LINENO 的奇怪行为。首先,这是我尝试记录错误的精简版本:

#!/bin/bash

set -E
trap 'echo Failed on line: $LINENO at command: $BASH_COMMAND && exit $?' ERR

现在,行为因故障发生的位置而异。例如,如果我按照上面的方法:

echo "Should fail at: $((LINENO + 1))"
false

我得到以下输出:

Should fail at: 6
Failed on line: 6 at command: false

一切如期而至。第 6 行是包含单个命令“false”的行。但是,如果我将失败的命令包装在一个函数中并像这样调用它:

function failure {
echo "Should fail at $((LINENO + 1))"
false
}
failure

然后我得到以下输出:

Should fail at 7
Failed on line: 5 at command: false

如您所见,$BASH_COMMAND 包含正确的失败命令:“false”,但是 $LINENO 将“失败”函数定义的第一行报告为当前命令。这对我来说毫无意义。有没有办法获取 $BASH_COMMAND 中引用的行的行号?

这种行为可能是 Bash 的旧版本所特有的。我暂时停留在 3.2.51 上。如果行为在以后的版本中发生了变化,那么知道是否有一种解决方法可以在 3.2.51 上获得我想要的值仍然很高兴。

编辑: 恐怕有些人会感到困惑,因为我将我的示例分成了 block 。让我试着澄清一下我拥有什么、得到什么以及想要什么。

这是我的脚本:

#!/bin/bash

set -E
function handle_error {
local retval=$?
local line=$1
echo "Failed at $line: $BASH_COMMAND"
exit $retval
}
trap 'handle_error $LINENO' ERR

function fail {
echo "I expect the next line to be the failing line: $((LINENO + 1))"
command_that_fails
}

fail

现在,我期望的是以下输出:

I expect the next line to be the failing line: 14
Failed at 14: command_that_fails

现在,我得到的是以下输出:

I expect the next line to be the failing line: 14
Failed at 12: command_that_fails

但是第 12 行不是 command_that_fails。第 12 行是 function fail {,帮助不大。我还检查了 ${BASH_LINENO[@]} 数组,它没有第 14 行的条目。

最佳答案

对于 4.1 之前的 bash 版本,需要一个特殊级别的可怕的、hacky 的、性能破坏的 hell 来解决一个问题,在这个问题上,系统在调用错误处理程序之前跳回到函数定义点。

#!/bin/bash

set -E
set -o functrace
function handle_error {
local retval=$?
local line=${last_lineno:-$1}
echo "Failed at $line: $BASH_COMMAND"
echo "Trace: " "$@"
exit $retval
}
if (( ${BASH_VERSION%%.*} <= 3 )) || [[ ${BASH_VERSION%.*} = 4.0 ]]; then
trap '[[ $FUNCNAME = handle_error ]] || { last_lineno=$real_lineno; real_lineno=$LINENO; }' DEBUG
fi
trap 'handle_error $LINENO ${BASH_LINENO[@]}' ERR

fail() {
echo "I expect the next line to be the failing line: $((LINENO + 1))"
command_that_fails
}

fail

关于bash - 如何获取失败的 Bash 命令的实际行号?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24398691/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com