Я просто играл с 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.
Однако , если I раскомментирует первую ловушку (та, что в 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 возвращает последнюю строку вызываемой функции как строку, которая вызвала ошибку в строке 21 ?
Заранее спасибо!
EDIT
На всякий случай, если кто-то заинтересован в функции отладки.Это производственная версия:
# 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