Подтвердить что ты не робот

Найти номер строки вызова функции из файла sourcing

Я пытаюсь найти способ узнать, из какого файла и номера строки вызывается функция. Функция находится в файле библиотеки, который создается моим 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}): ""$*"
4b9b3361

Ответ 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

Ответ 2

Для этой цели можно использовать три переменные массива:

  • FUNCNAME
  • BASH_SOURCE
  • BASH_LINENO

Для получения дополнительной информации см. следующий ответ:

Ответ 3

Вдохновленный @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. Не стесняйтесь предлагать улучшения сути. Я попытаюсь сохранить этот ответ обновленным, если произойдут какие-либо изменения, но я не могу гарантировать.