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)