I don't know what's wrong but this script doesn't work. It should be always goes back to menu everytime I press 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
It works for the first CTRL+C but the second times it just doesn't works.
I'm new to this so please don't judge me ;)
Any helps appreciated :) Thanks.
EDIT:
Actually, I found this works
#!/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
But is that OK?
As a rule of thumb, you want to do as little as possible during signal handling. Especially if you're intending to recover from the signal instead of exiting, it is generally preferable to simply record that the signal was sent and then actually handle the signal in your "normal" code.
So instead of recursively calling functions (inside traps) in order to navigate, let's keep track of the current page and display it in a loop. Then, all the SIGINT handler has to do is update the current-page variable.
Here's a working demo of a three-page flow like your example (using select
to navigate, but any approach would work if you don't like 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
page
on SIGINT/^Cread
in a subshell
read
specificallyexit
if the read succeedsGive it a whirl! It works great on my system (Bash 4.3)