SIGINT 未在“${FUNCNAME[@]}”中清除

Nic*_*ull 6 bash signals function

执行以下脚本,被键盘输入Ctrl+打断,C如图所示:

$ function a() { echo "Performing"; sleep 10; echo "Performed"; }
$ a
Performing
^C
$ echo "${FUNCNAME[@]}"
a source
Run Code Online (Sandbox Code Playgroud)

如果我们多次重复SIGINTduring 函数a,我们最终会得到这样的场景:

...

$ a
Performing
^C
$ a
Performing
^C
$ echo "${FUNCNAME[@]}"
a a a a a a a a a source
Run Code Online (Sandbox Code Playgroud)

为了演示这个问题,让我们有另一个函数,b,它给出了一个message_error函数,也定义如下:

$ function message_error() {
>   local MESSAGE="$1"
>
>   # FUNCNAME[1], as [0] is `message_error`, gets the calling function
>   echo "[[ ERROR ]] ${FUNCNAME[1]}: $MESSAGE"
>   echo "Rest of the stack: ${FUNCNAME[@]}"
>}
$ function b() { message_error "Oh no"; }
$ b
[[ ERROR ]] b: Oh no
Rest of the stack: message_error b a a a a a a a a a source
Run Code Online (Sandbox Code Playgroud)

即使在 中调用该函数source,也a显示为调用函数。如您所见,所有这些a功能都已退出。但是,它们保留在 FUNCNAME 数组中。

为什么是这样?SIGINT 无法删除它后如何删除它?请注意,所有函数都来自大量常用函数~/.bash_functions,如果这些函数的来源会影响它们解释 SIGINT 的方式。

agc*_*agc 1

由于FUNCNAME只读数组,因此可能无法删除其中的项目。这似乎unset FUNCNAME可行,但这也破坏了bash的特殊 FUNCNAME 行为。

FUNCNAME可以通过使用以下方法来防止垃圾trap

$ trap : SIGINT
$ function a() {  echo "Performing"; sleep 10; echo "Performed"; } 
$ a
Performing
^C
$ echo %"${FUNCNAME[@]}"%
%%
Run Code Online (Sandbox Code Playgroud)

要禁用上述预防措施,请执行trap - SIGINT