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)
如果我们多次重复SIGINT
during 函数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 的方式。
由于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
。