当我将“陷阱”与选择循环结合使用时,即当我尝试在显示选项时按 CTRL+C 来突破时,它只会在终端中打印 ^C。如果我从脚本中删除“陷阱”,它通常会退出,也就是说它会接受 CTRL+C。
我已经在两种不同版本的 bash 上对此进行了测试(一种随 CentOS 提供,另一种随 Fedora 提供),我对来自 Fedora(4.4.23(1)-release)的那个有问题。CentOS 附带的 Bash 版本 4.2.46(2)-release 似乎工作正常。我还在本地终端和远程(通过 ssh)上对此进行了测试。问题总是在 Fedora 方面。
我将发布代码以查看我在说什么
这个不行:
#!/bin/bash
trap exit SIGINT
select opt in One Two Three; do
break
done
如果我要删除整个 'trap exit SIGINT' 行,它将正常工作并接受 CTRL+C 没有问题。
任何想法如何解决或绕过这个?
您可以通过打开posix模式来绕过它,或者使用
--posix
选项,或者暂时使用set -o posix
:有关此行为的解释,您可以查看内置
zread()
函数使用的函数read
(也由 bash in 内部调用select
):由于某些特殊原因,
executing_builtin
仅在read
显式调用内置函数时设置,而不是在由 调用时设置select
。这看起来很像一个错误,而不是故意的。在posix模式下运行时,信号将取消
read
内置。在这种情况下,zreadintr()
被调用,与 不同的是,在运行陷阱后zread()
不会重新调用中断的系统调用。read(2)
见builtins/read.def
:read
有关 bash内置的“重新启动”的更多详细信息,请点击此处。手册中的相关部分
bash
是(我相信;至少它的行为是这样的):select
所以你的陷阱处理程序在循环体执行之前不会被调用,因为bash
它正在等待命令完成。一旦接收到输入select
,陷阱处理程序将执行。以下修改后的脚本更好地说明了这一点:
运行它(使用
bash
5.0.3),选择,然后1
按,然后选择。 Ctrl+CEnter3
陷阱处理程序在当前输入 (
3
) 已被接受且select
循环体之前执行时执行。当我按下after时,不会执行陷阱处理程序,因为在提示符处按下只会重新显示菜单。EnterCtrl+CEnter
select