17

我正在尝试找到一种方法来找出调用函数的文件和行号。该函数位于由我的脚本提供的库文件中。

文件1:

$source file2
$warn_me "Error: You didn't do something"

文件2:

$function warn_me() {
$  message=????
$  echo ${message}
$}

期望的输出: $:file1:Line 2: Error: You didn't do something

函数调用已经在许多文件中发生了很多次,所以我试图找到一种方法来做到这一点而不改变它。

以前,warn_me 函数是在每个使用它的文件中定义的,并且这样处理:

$local message="$BASH_SOURCE:(""${BASH_LINENO}): ""$*"
4

3 回答 3

16

你似乎在寻找caller它。

$ cat h.sh 
#! /bin/bash
function warn_me() {
  echo "$@"
  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
于 2012-06-18T21:19:20.727 回答
11

受@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}"
}

更新:我修正了一个错字并添加了一个错误消息参数。所以函数的第一个参数是要添加到堆栈跟踪的错误消息。顺便说一句,如果您的脚本在bash的标准输入上提供(在大多数情况下是个坏主意),那么第一个位置将会丢失。如果需要,则在for循环中将其更改为i<$stack_size + 1. 但正如我所说,将您的脚本提供给 bash 的标准输入并不是一个好主意,这就是为什么.

更新 2:我发现我对此有一个较旧的答案。想更好地将代码的更新版本保存在一个地方。所以决定做一个要点。随时提出对要点的改进建议。如果发生任何更改,我会尝试更新此答案,但我不能保证。

于 2013-07-18T21:20:10.857 回答
9

有三个数组变量可用于此目的:

  • FUNCNAME
  • BASH_SOURCE
  • BASH_LINENO

有关详细信息,请参阅以下答案:

于 2012-06-18T21:18:10.490 回答