bash - Bash 陷阱 SIGINT 多次不起作用
问题描述
我不知道出了什么问题,但这个脚本不起作用。每次按 CTRL+C 时,它应该总是返回菜单。
#!/bin/bash
func_info()
{
clear
echo "This is info page."
read -p "Press CTRL+C to back to menu or press enter exit..."
exit
}
func_menu()
{
clear
trap - SIGINT
echo "This is menu page."
read -p "Press enter to go to info page..."
trap func_menu SIGINT
func_info
}
func_menu
它适用于第一次 CTRL+C 但第二次它不起作用。
我是新手,所以请不要评判我;)
任何帮助表示赞赏:) 谢谢。
编辑:
实际上,我发现这行得通
#!/bin/bash
func_info()
{
clear
echo "This is info page."
read -p "Press CTRL+C to back to menu or press enter exit..."
exit
}
func_menu()
{
clear
echo "This is menu page."
read -p "Press enter to go to info page..."
( trap exit SIGINT; func_info )
func_menu
}
func_menu
但是这样可以吗?
解决方案
根据经验,您希望在信号处理期间尽可能少做。特别是如果您打算从信号中恢复而不是退出,通常最好简单地记录信号已发送,然后在“正常”代码中实际处理信号。
因此,与其为了导航而递归调用函数(在陷阱内),不如让我们跟踪当前页面并在循环中显示它。然后,所有 SIGINT 处理程序所要做的就是更新当前页面变量。
这是一个像您的示例一样的三页流程的工作演示(select
用于导航,但如果您不喜欢,任何方法都可以使用select
):
pages=(info news contact)
page=
info() { echo "For info, see the news page"; }
news() { echo "$(date +%Y-%m-%d): No news today"; }
contact() { echo "We cannot be reached."; }
while true; do
trap - SIGINT
clear
if [[ -n "$page" ]]; then
trap 'page=; continue' SIGINT
echo "This is the ${page} page"
"$page" # invokes the function named $page
( read -p $'\nPress CTRL+C to go back to menu or press enter to exit...' )
exit
else
echo "This is the menu page"
echo "Select a page number and press enter to go there."
select page in "${pages[@]}"; do
if [[ -n "$page" ]]; then break; fi
done
fi
done
- 在循环开始时清除陷阱,以便 ^C 从菜单页面退出脚本
- 显示页面时,配置
page
在 SIGINT/^C 上重置的陷阱 read
在一个子外壳中- 正如您所发现的,子shell 会有所帮助,因为 SIGINT/^C 会整体中断子shell,而不是
read
专门中断 - 并且只有
exit
读取成功
- 正如您所发现的,子shell 会有所帮助,因为 SIGINT/^C 会整体中断子shell,而不是
试一试!它在我的系统上运行良好(Bash 4.3)
推荐阅读
- c++ - 使用 Boost Interprocess 创建托管共享内存需要很长时间
- http - 隐藏 QR 扫描后通过 URL 发送的请求
- java - 边界计时器在 Activiti 6 中不起作用
- javascript - 博客中的 PHP 经典模板
- javascript - 更快地将数组字段复制到另一个数组中
- jsf-2 - window.open(url, '_blank') 从后端打开两个窗口
- c# - IIS 获取 HttpRequest Asp.net 的套接字
- visual-studio-2017 - 由安装程序安装时 VS2017 项目无法正常工作的问题
- reactjs - React-router-dom 在卸载组件之前首先调用构造函数
- python - 如何更改复选框名称的字体大小