bash调用程序内建函数无法从导出的函数运行,为什么? [英] bash caller builtin stops working from exported function, why?
问题描述
使用 bash
和导出函数给我一个非常奇怪的问题,使我可以可靠地回答内置调用者$ c $的调用c>。
I have very strange issues using bash
and exported function to give me a reliable answer to the call of the builtin caller
.
这是我用来说明此问题的设置:Bash脚本 bar
定义并导出函数 bar1
和 bar2
。 bar2
调用 bar1
。 Bash脚本 bar
然后执行bash脚本 foo
,它将调用 bar1
。
Here's my setup to illustrate this issue: Bash script bar
defines and exports function bar1
and bar2
. bar2
calls bar1
. Bash script bar
then execute bash script foo
which will call bar1
.
然后,仅在 bar1
的呼叫之后,内置的呼叫方才会中断。这正常吗?你能解释为什么吗?您可以简化以下暴露问题的代码吗?
The caller builtin will then break only after the call of bar1
. Is this normal ? can you explain why ? can you simplify the following code that exposes the issue ?
要完全清楚,这是在您的系统上重现的方法:构建两个文件:
To be perfectly clear, here's how to reproduce on your system: Build both file:
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:
我期望(行号可接受的变化):
I expected (with acceptable variations on the line numbers):
$ ./bar
bar1 BEFORE: 9 main ./foo
bar2 IN: 5 bar ./foo
bar1 AFTER: 9 main ./foo
最终,我的问题是:我该如何规避此问题并得到呼叫者 >在所有情况下?
Ultimately, my question would be: how could I circumvent this issue and get the caller in all cases ?
附加信息:
- bash版本:
4.3.42(1)-发行版(x86_64-pc-linux-gnu)
来自ubuntu软件包4.3-14ubuntu1
。
- bash version:
4.3.42(1)-release (x86_64-pc-linux-gnu)
from ubuntu package4.3-14ubuntu1
.
推荐答案
这是bash中的 bug 。在版本4.4中已修复该问题。
This is a bug in bash. It was fixed in version 4.4.
存在导出功能时, BASH_SOURCE
变量未正确维护。您可以通过显示 FUNCNAME
, BASH_SOURCE
, BASH_LINENO
特殊变量:
In the presence of exported functions, the BASH_SOURCE
variable is not properly maintained. You can check it by displaying the contents of the FUNCNAME
, BASH_SOURCE
, BASH_LINENO
special variables:
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
中,但是只要有函数返回,就会弹出最高堆栈帧。
As you can see, stack frames corresponding to invocations of exported functions aren't added to BASH_SOURCE
, but whenever a function returns the topmost stack frame is popped.
请注意 FUNCNAME
变量不受此错误影响。因此,如果仅需要呼叫者的姓名,则可以将其作为 $ {FUNCNAME [1]}
获得。
Note that the FUNCNAME
variable is not affected by this bug. Thus, if you need only the name of the caller you can obtain it as ${FUNCNAME[1]}
.
这篇关于bash调用程序内建函数无法从导出的函数运行,为什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!