Bash 多次陷阱 SIGINT 不起作用
Bash Trap SIGINT Multiple Times Doesn't Work
我不知道出了什么问题,但这个脚本不起作用。
每次我按 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
但是这样可以吗?
根据经验,您希望在信号处理期间尽可能少。特别是如果您打算从信号中恢复而不是退出,通常最好只记录信号已发送,然后在 "normal" 代码中实际处理信号。
因此,与其为了导航而递归调用函数(内部陷阱),让我们跟踪当前页面并在循环中显示它。然后,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从菜单页面退出脚本
- 显示页面时,配置一个陷阱,在 SIGINT/^C
上重置 page
read
在子 shell 中
- 如您所见,子 shell 有帮助,因为 SIGINT/^C 会中断整个子 shell,而不是
read
具体
- 并且仅
exit
如果读取成功
试一试!它在我的系统上运行良好 (Bash 4.3)
我不知道出了什么问题,但这个脚本不起作用。 每次我按 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
但是这样可以吗?
根据经验,您希望在信号处理期间尽可能少。特别是如果您打算从信号中恢复而不是退出,通常最好只记录信号已发送,然后在 "normal" 代码中实际处理信号。
因此,与其为了导航而递归调用函数(内部陷阱),让我们跟踪当前页面并在循环中显示它。然后,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从菜单页面退出脚本
- 显示页面时,配置一个陷阱,在 SIGINT/^C 上重置
read
在子 shell 中- 如您所见,子 shell 有帮助,因为 SIGINT/^C 会中断整个子 shell,而不是
read
具体 - 并且仅
exit
如果读取成功
- 如您所见,子 shell 有帮助,因为 SIGINT/^C 会中断整个子 shell,而不是
page
试一试!它在我的系统上运行良好 (Bash 4.3)