gpt4 book ai didi

bash - bash 陷阱 ERR 中的神秘 LINENO

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

我只是在玩 bash 来绕过这个夏天午后的炎热,突然间我得到了一个神秘的结果,我无法确定它的来源。

让我稍微解释一下。

我正在使用 trap ERR 为我的 bash 脚本创建一些调试函数。

这是运行良好的脚本:

traperror () {
local err=$? # error status
local line=$1 # LINENO
[ "$2" != "" ] && local funcstack=$2 # funcname
[ "$3" != "" ] && local linecallfunc=$3 # line where func was called
echo "<---"
echo "ERROR: line $line - command exited with status: $err"
if [ "$funcstack" != "" ]; then
echo -n " ... Error at function ${funcstack[0]}() "
if [ "$linecallfunc" != "" ]; then
echo -n "called at line $3"
fi
echo
fi
echo "--->"
}
#trap 'traperror $LINENO ${FUNCNAME}' ERR

somefunction () {
trap 'traperror $LINENO ${FUNCNAME} $BASH_LINENO' ERR
asdfas
}

somefunction

echo foo

为了清楚起见,输出是(stderr 转到 /dev/null;bash 错误当然是 foo.sh: line 23: asdfas: command not found 这如您所知,错误代码 127)

~$ bash foo.sh 2> /dev/null 
<---
ERROR: line 21 - command exited with status: 127
... Error at function somefunction() called at line 24
--->
foo

所有行号都正确,第 21 行是函数“somefunction”的启动位置,第 24 行是调用它的位置。

但是如果我取消注释第一个陷阱(main 中的那个)我会得到这个输出:

~$ bash foo.sh 2> /dev/null 
<---
ERROR: line 21 - command exited with status: 127
... Error at function somefunction() called at line 24
--->
<---
ERROR: line 15 - command exited with status: 127
--->
foo

如果我取消注释第一个陷阱并注释第二个陷阱,我会发现错误在第 23 行,这也是正确的,因为它是放置错误命令的绝对行。

~$ bash foo.sh 
<---
ERROR: line 23 - command exited with status: 127
--->
foo

所以我的问题是:为什么是第 15 行?该行号从何而来?第 15 行是 trap 函数的最后一行。谁能用简单的英语解释为什么 trap 返回它调用的函数的最后一行作为产生第 21 行错误的行?

提前致谢!

编辑

以防万一有人对调试功能感兴趣。这是生产版本:

# Copyright (c): Hilario J. Montoliu <hmontoliu@gmail.com>
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or (at your
# option) any later version. See http://www.gnu.org/copyleft/gpl.html for
# the full text of the license.

set -o errtrace
trap 'traperror $? $LINENO $BASH_LINENO "$BASH_COMMAND" $(printf "::%s" ${FUNCNAME[@]})' ERR

traperror () {
local err=$1 # error status
local line=$2 # LINENO
local linecallfunc=$3
local command="$4"
local funcstack="$5"
echo "<---"
echo "ERROR: line $line - command '$command' exited with status: $err"
if [ "$funcstack" != "::" ]; then
echo -n " ... Error at ${funcstack} "
if [ "$linecallfunc" != "" ]; then
echo -n "called at line $linecallfunc"
fi
else
echo -n " ... internal debug info from function ${FUNCNAME} (line $linecallfunc)"
fi
echo
echo "--->"
}

somefunction () {
asdfasdf param1
}

somefunction

echo foo

它将作为:

~$ bash foo.sh 2> /dev/null 
<---
ERROR: line 26 - command 'asdfasdf param1' exited with status: 127
... Error at ::somefunction::main called at line 29
--->
<---
ERROR: line 22 - command 'asdfasdf param1' exited with status: 127
... internal debug info from function traperror (line 0)
--->
foo

最佳答案

一些相关事实/背景信息:

  • ERR 上的陷阱不会被 shell 函数继承,即使它们获得了环境的其余部分,除非设置了 errtrace

    <
  • 函数的退出状态是其最后一条命令的退出状态。

我对发生的事情的猜测:

在两个陷阱都激活的情况下,

  • 不存在的命令触发函数中的 ERR 陷阱。 LINENO 是不存在的命令。
  • 陷阱执行完毕。由于不存在的命令是最后一个命令,函数的返回状态为非零,因此触发了 shell 中的 ERR 陷阱。 LINENO 仍然设置为 traperror 的最后一行,因为它是执行的最后一行并且仍然是当前行,因为尚未执行新行。<

在只有shell tr​​ap激活的情况下(函数中的那个被注释掉了)

  • 不存在的命令是函数中的最后一个命令,因此导致函数返回非零值,从而导致触发 shell 的 ERR 陷阱。出于与上述相同的原因,LINENO 是函数的最后一行,因为它是执行的最后一行并且仍然是当前行。

关于bash - bash 陷阱 ERR 中的神秘 LINENO,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6928946/

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