BASH呼叫者内置素网已停止从导出功能进行工作,为什么



我使用 bash和导出功能有非常奇怪的问题,以使我对内置caller的呼叫有可靠的答案。

这是我的设置来说明此问题:BASH脚本bar定义和导出功能bar1bar2bar2调用bar1。bash脚本bar然后执行bash脚本foo,该脚本将调用bar1

caller内置的素in将仅在bar1的调用之后断开。这是正常的吗?你能解释为什么吗?您可以简化揭示问题的以下代码吗?

要完全清楚,这是在系统上复制的方法:构建两个文件:

cd /tmp
cat <<"EOF" > foo 
#!/bin/bash
bar1
EOF
chmod +x foo
cat <<"EOF" > bar 
#!/bin/bash
bar2() {
    echo "$FUNCNAME IN: $(caller 0)" >&2 
} 
export -f bar2
bar1() {
    echo "$FUNCNAME BEFORE: $(caller 0)" >&2
    bar2
    echo "$FUNCNAME AFTER: $(caller 0)" >&2 
}
export -f bar1
./foo
EOF
chmod +x bar

然后您可以小提琴并查看:

$ ./bar
bar1 BEFORE: 3 main ./foo
bar2 IN: 
bar1 AFTER: 

我期望的(在行号上有可接受的变化):

$ ./bar
bar1 BEFORE: 9 main ./foo
bar2 IN: 5 bar ./foo
bar1 AFTER: 9 main ./foo

最终,我的问题是:在所有情况下,我如何绕过此问题并获取呼叫者

附加信息:

  • BASH版本:4.3.42(1)-release (x86_64-pc-linux-gnu)来自Ubuntu软件包4.3-14ubuntu1

这是bash中的一个错误。它在版本4.4。

中修复了

在存在导出函数的情况下,BASH_SOURCE变量无法正确维护。您可以通过显示FUNCNAMEBASH_SOURCEBASH_LINENO特殊变量的内容来检查它:

cd /tmp
cat <<"EOF" > foo 
#!/bin/bash
bar1 
EOF
chmod +x foo
cat <<"EOF" > bar 
#!/bin/bash
bar2() {
    echo "$FUNCNAME IN: $(caller 0) [${FUNCNAME[@]}] [${BASH_SOURCE[@]}] [${BASH_LINENO[@]}]" >&2 
} 
export -f bar2
bar1() {
    echo "$FUNCNAME BEFORE: $(caller 0) [${FUNCNAME[@]}] [${BASH_SOURCE[@]}] [${BASH_LINENO[@]}]" >&2
    bar2
    echo "$FUNCNAME AFTER: $(caller 0) [${FUNCNAME[@]}] [${BASH_SOURCE[@]}] [${BASH_LINENO[@]}]" >&2 
} 
export -f bar1
./foo
EOF
chmod +x bar

./bar的输出:

bar1 BEFORE: 3 main ./foo [bar1 main] [./foo] [3 0]
bar2 IN:  [bar2 bar1 main] [./foo] [1 3 0]
bar1 AFTER:  [bar1 main] [] [3 0]

如您所见,与导出功能的调用相对应的堆栈帧不会添加到BASH_SOURCE中,但是每当函数返回时,弹出了最上方的堆栈帧。

请注意,FUNCNAME变量不受此错误的影响。因此,如果您仅需要呼叫者的名称,则可以作为${FUNCNAME[1]}获取。

最新更新