我有以下脚本
#!/bin/bash
exec 5> >(logger -t $0)
BASH_XTRACEFD="5"
set -x
trap _reboot INT
DIALOG_TITLE="This is fancy dialog title"
_reboot() {
echo Exiting
exit
}
dialog --title "${DIALOG_TITLE}" --yesno "Welcome to Dialog" 0 0
但是,当我执行 CTRL+C 时,脚本将退出而不打印任何内容。如果我删除其中一个,set -x
否则BASH_XTRACEFD="5"
它将正常工作并捕获陷阱并执行 _reboot 函数。但是如果我将两者都保留(我需要出于调试目的) - 那么 trap 就失去了所有意义。
退出代码是 141,当我使用 CTRL+C 退出时,这很有趣。如果我让脚本运行,它很自然地会以 0 退出,但是如果我删除set -x
或中的任何一个,BASH_XTRACEFD="5"
然后CTRL+C
我将以 55 退出。
由于某种原因,这种情况仅在屏幕上出现对话框时发生。例如,如果我这样做
while true; do
sleep 5
done
然后exit with CTRL+C
trap就会被执行。
我需要帮助来解决这个问题。
编辑:可能值得一提的是 bash 版本是 5.1.16,在 Alpine 3.16 上运行
答案1
对话框使用 ncurses,它捕获SIGINT
,如initscr
联机帮助页部分中所述信号处理器:
SIGINT
处理程序尝试在退出时清理屏幕。虽然它通常按预期工作,但也有局限性:
- 遍历 SCREEN 列表是不安全的,因为所有列表管理都是在没有任何信号阻塞的情况下完成的。
- 在打开 REENTRANT 的系统上,set_term 使用的函数可能会死锁或以其他方式出现错误。
- endwin 调用其他函数,其中许多函数使用 stdio 或其他库函数,这显然是不安全的。
只有当子进程没有首先捕获信号时,bash 才会“看到”该信号。