Ответ 1
Вы ищете caller
.
$ cat h.sh
#! /bin/bash
function warn_me() {
echo "[email protected]"
caller
}
$ cat g.sh
#!/bin/bash
source h.sh
warn_me "Error: You didn't do something"
$ . g.sh
Error: You didn't do something
3 g.sh
Я пытаюсь найти способ узнать, из какого файла и номера строки вызывается функция. Функция находится в файле библиотеки, который создается моим script.
file1:
$source file2
$warn_me "Error: You didn't do something"
file2:
$function warn_me() {
$ message=????
$ echo ${message}
$}
Желаемый результат: $: file1: Строка 2: Ошибка: вы ничего не сделали
Вызов функции уже встречается много раз во многих файлах, поэтому я пытаюсь найти способ сделать это, не меняя этого.
Ранее функция warn_me была определена в каждом используемом файле, и об этом позаботились так:
$local message="$BASH_SOURCE:(""${BASH_LINENO}): ""$*"
Вы ищете caller
.
$ cat h.sh
#! /bin/bash
function warn_me() {
echo "[email protected]"
caller
}
$ cat g.sh
#!/bin/bash
source h.sh
warn_me "Error: You didn't do something"
$ . g.sh
Error: You didn't do something
3 g.sh
Для этой цели можно использовать три переменные массива:
FUNCNAME
BASH_SOURCE
BASH_LINENO
Для получения дополнительной информации см. следующий ответ:
Вдохновленный @nosid и @Wrikken, я написал небольшую функцию, чтобы поместить текущую трассировку стека в переменную с именем $STACK. Возможно, было бы полезно выводить пользователю местоположение, где произошла ошибка. Слишком плохо bash не имеет встроенного printStackTrace... Надеюсь, кто-то найдет его удобным в своих проектах.
function get_stack () {
STACK=""
local i message="${1:-""}"
local stack_size=${#FUNCNAME[@]}
# to avoid noise we start with 1 to skip the get_stack function
for (( i=1; i<$stack_size; i++ )); do
local func="${FUNCNAME[$i]}"
[ x$func = x ] && func=MAIN
local linen="${BASH_LINENO[$(( i - 1 ))]}"
local src="${BASH_SOURCE[$i]}"
[ x"$src" = x ] && src=non_file_source
STACK+=$'\n'" at: "$func" "$src" "$linen
done
STACK="${message}${STACK}"
}
Обновление: я исправил опечатку и добавил параметр сообщения об ошибке. Таким образом, первым параметром функции является сообщение об ошибке, которое должно быть добавлено в трассировку стека. Кстати, если ваш script поставлен на bash
stdin (в большинстве случаев это плохая идея), то первая позиция будет потеряна. Если необходимо, то в цикле for
измените его на i<$stack_size + 1
. Но, как я уже сказал, не рекомендуется передавать ваш script в stdin bash, вот почему.
Обновление 2: я нашел, что у меня есть более старый ответ об этом. Мысль лучше поддерживать обновленную версию кода в одном месте. Поэтому решили сделать gist. Не стесняйтесь предлагать улучшения сути. Я попытаюсь сохранить этот ответ обновленным, если произойдут какие-либо изменения, но я не могу гарантировать.