Bash while command - bash

I have created a bash menu script, using options 1-8. For my second menu option I am using the while command to display the current time and date. However, when I press Ctrl+C to end the display of the date it jumps out of the entire script rather than redisplay the menu. Is there a way around this?

yeah, make functions
#more code here ...
display_main_menu() {
while true; do
echo -e "Please select an action:"
echo -e " "
echo -e "1 - Transfer a local file to all servers."
echo -e "2 - Execute a command(s) on all servers."
echo -e "9 - Display all servers."
echo -e "0 - Exit"
echo ""
read -p "" action
case $action in
"1" ) function_to_transfer_file ;;
"2" ) function_to_execute_command ;;
"9" ) function_to_show_server;;
"0" ) exit;;
* ) echo "Please select a valid action.";;
esac
done
}
#more code here ...
Make multiple functions, one for each option in primary menu. Here option 0 exits the script completely.
For secondary menu functions ... option 0 should execute function display_main_menu

You want catch the signal SIGINT (Ctrl+C) and break
trap 'break' SIGINT
For example:
#!/bin/bash
trap 'break' SIGINT
while :
do
sleep 1
echo "foo"
done
echo "bar"
Take a look here to have more details:
http://tldp.org/LDP/Bash-Beginners-Guide/html/chap_12.html
#!/bin/bash
#more code here ...
display_main_menu() {
while true; do
echo -e "Please select an action:"
echo -e " "
echo -e "1 - display time"
echo -e "2 - Execute a command(s) on all servers."
echo -e "9 - Display all servers."
echo -e "0 - Exit"
echo ""
read -p "" action
case $action in
"1" ) trap 'break' SIGINT; while true; do echo "$(date '+%D %T' )"; sleep 1; done ;;
"2" ) function_to_execute_command ;;
"9" ) function_to_show_server;;
"0" ) exit;;
* ) echo "Please select a valid action.";;
esac
done
}
display_main_menu

Related

Return to previous commands in bash script?

I'm trying to implement a prev option in my bash script to go back to the previous "menu", as well as a way for the script to ask for user input again if no variable is set for $name.
Heres my bash script:
#!/bin/bash
#Menu() {
for (( ; ; ))
do
beginORload=
echo "Choose option:"
echo "1 - Begin"
echo "2 - Load"
read -p "?" beginORload
#}
#Begin() {
if [ "$beginORload" -eq "1" ]
then
clear
for (( ; ; ))
do
echo "Beginning. What is your name?"
read -p "?" name
#If "prev" specified, go back to #Menu()
if [ "$name" -eq "prev" ]
then
Menu
fi
#If nothing specified, return to name input
if [ -z ${name+x} ]
then
Begin
else
break
fi
echo "Hi $name !"
done
fi
done
In batch, I could simply do:
:menu
echo Choose option:
echo 1 - Begin
echo 2 - Load
[...]
:begin
[...]
if "%name%==prev" goto menu
if "%name%==" goto begin
the issue is I keep running into errors all over the place, and I can't figure out what to type to get it to work
im running Yosemite btw. Thankyou
Something like this is close to what you expect:
while [[ $answer -ne '3' ]];do
echo "Choose option:"
echo "1 - Begin"
echo "2 - Load"
echo "3 - Exit"
read -p "Enter Answer [1-2-3]:" answer
case "$answer" in
1) while [[ "$nm" == '' ]];do read -p "What is your Name:" nm;done # Keep asking for a name if the name is empty == ''
if [[ $nm == "prev" ]];then nm=""; else echo "Hello $nm" && break; fi # break command breaks the while wrapper loop
;;
2) echo 'Load' ;;
3) echo 'exiting...' ;; # Number 3 causes while to quit.
*) echo "invalid selection - try again";; # Selection out of 1-2-3 , menu reloaded
esac # case closing
done # while closing
echo "Bye Bye!"
As a general idea you can wrap up your case selection in a while loop which will break under certain circumstances (i.e If Option 3 is selected or if a valid name is given (not blank - not prev)
PS1: In bash you compare integers with -eq , -ne, etc but you compare strings with == or !=
PS2: Check the above code online here

Bash: option menu no wait for enter

I have an options menu function:
function()
{
echo "1 Option 1"
echo "2 Option 2"
echo "3 Option 3"
echo "q Exit"
read -p "Select 1-3 ή \"q\" to quit: " i
case "$i" in
1)
echo "option 1"
echo;;
2)
echo "option 2"
echo;;
3)
echo "option 3"
echo;;
q) echo -e "\033[01;33mexit!!!\033[39m"
sleep 1
clear
exit ;;
*)
echo "Unknown command"
read -s -n 1 -p "Press any key to continue…"
echo
esac
}
while:
do function
done
The above works fine, but need to press enter after I input the number before the command run. Is there any way to immediately run the command when I press the key?
You've got the answer right in your sample code (in the second read). You want to take advantage of bash's read -n 1 capability (note, this is not POSIX compliant, so it won't reliably work in /bin/sh unless that happens to map to bash):
read -n 1 -p "Select 1-3 ή \"q\" to quit: " i

Preventing a shell script from exiting with Control C

so I am trying to create a script which gives the user some options to do things, one of that option is to exit the script. However, I want to prevent the user from exiting the script using Control c so that the only way to exit is to select the right option. Is it possible to make the script so that when the user hits control c, the program will not exit, but rather it would echo something like "enter 0 to exit"?
#!/bin/bash
# Acts as a simple administration menu
OPTION=0
echo "-----------------Admin Menu-------------------"
echo "Please select one of the following options: "
echo ""
echo "1 - Run top."
echo "2 - Show system uptime."
echo "3 - Show logged in users."
echo "4 - Exit Menu."
echo "5 - Reprint this menu."
echo "----------------------------------------------"
echo "Please choose an option (5 to reprint menu):"
read OPTION
while [ "$OPTION" -ne 4 ]
do
if [ "$OPTION" -eq 1 ]; then
clear
top -n1
elif [ "$OPTION" -eq 2 ]; then
clear
uptime
elif [ "$OPTION" -eq 3 ]; then
clear
who
elif [ "$OPTION" -eq 4 ]; then
clear
OPTION=4
elif [ "$OPTION" -eq 5 ]; then
clear
echo "------------COSC 2306 Admin Menu--------------"
echo "Please select one of the following options: "
echo ""
echo "1 - Run top."
echo "2 - Show system uptime."
echo "3 - Show logged in users."
echo "4 - Exit Menu."
echo "5 - Reprint this menu."
echo "----------------------------------------------"
else
clear
echo "ERROR: Incorrect Input."
fi
echo "Please choose an option (5 to reprint menu):"
read OPTION
done
clear
You can use the trap built-in to catch SIGINT ( ctrl + C generates the signal SIGINT) and print your message:
trap 'echo "enter 0 to exit"' SIGINT
Similarly you can catch other signals too. To get the list of signals use kill -l.

Bash Input Variables & Loop

My script
#!/bin/bash
while :
do
echo "[*] 1 - Create a gnome-terminal"
echo "[*] 2 - Display Ifconfig"
echo -n "Pick an Option > "
read Input
if [ "$Input" = "1" ]; then
gnome-terminal
sleep 3
echo "[*] 1 - Create a gnome-terminal"
echo "[*] 2 - Display Ifconfig"
echo -n "Pick an Option > "
read Input
fi
if [ "$Input" = "2" ]; then
clear
ifconfig
echo "[*] 1 - Create a gnome-terminal"
echo "[*] 2 - Display Ifconfig"
echo -n "Pick an Option > "
read Input
fi
done
Doesn't reuse the Input variable, say if you want to run the ifconfig option multiple times in a row. It rechecks the first variable string to see if it matches "1", and when it doesn't it echoes back the list of options. Any ideas on how to make any input variable accessible regardless of when it is used?
The problem is that you're writing out the menu twice on each iteration. Stop doing that:
#!/bin/bash
while :
do
echo "[*] 1 - Create a gnome-terminal"
echo "[*] 2 - Display Ifconfig"
echo -n "Pick an Option > "
read Input
if [ "$Input" = "1" ]; then
gnome-terminal
sleep 3
fi
if [ "$Input" = "2" ]; then
clear
ifconfig
fi
done
Use select instead of rolling your own menu:
choices=(
"Create a gnome-terminal"
"Display Ifconfig"
)
PS3="Pick an Option > "
select action in "${choices[#]}"; do
case $action in
"${choices[0]}") gnome-terminal; sleep 3;;
"${choices[1]}") clear; ifconfig;;
*) echo invalid selection ;;
esac
done
select gives you an infinite loop by default. If you want to break out of it, put a break statement into the case branch.

Programmatically shut down or sleep sandboxed application Mac

I am trying to make an application for the Mac App Store that will shut down/sleep the Mac after a user-set time. I have tried to use AppleScript, but that won't work if I am going to use it in Sandbox mode, I have tried to Google for a solution, but I cant seem to figure it out.
Hope someone can give me a hint or link to relevant documentation.
edit: made it more precise to what I desire to accomplish.
There is no way to do this. You may try to get a temporary-exception to run "shutdown" or "halt" thru BSD-layer but I doubt that such an app will pass the App Store review as these are tasks that require superuser / admin rights.
I wrote a script once. But I don't know whether it still works. Maybe it gives you at least a clue. Sleep still works - shutdown maybe causes problems if programs are blocking the shutdown.
(Not the prettiest code but it worked for me.)
#/bin/sh
#v1.0.0
#by Sapphire
echo "-----------------------------------------------------"
echo "* Sleep Timer *"
echo "-----------------------------------------------------"
echo "Please enter option: Sleep '1' or shutdown '0'"
echo -n "Option: "
read option
while :
do
if [ $option -eq 1 -o $option -eq 0 ]
then
break
fi
echo "<<ERROR: Only number: 1 or 0 allowed...>>"
echo "Please rnter option: Sleep '1' or shutdown '0'"
echo -n "Option: "
read option
done
echo "Please enter countdown (min):"
echo -n "Minutes: "
read shutDown
while :
do
if [ $shutDown -gt 0 -a $var -eq $var 2> /dev/null ]
then
break
fi
echo "<<ERROR: Positive number expected...>>"
echo "Please enter countdown (min):"
echo -n "Minutes: "
read shutDown
done
echo "*****************************************************"
echo "Counter has been started"
echo "'/!\ Kill countdown with CTRL-C /!\'"
echo -n "Envoking command in: "
date +"%H:%M %Z"
echo "*****************************************************"
if [ $option -eq 0 ]
then
echo "Shutdown in: "
fi
if [ $option -eq 1 ]
then
echo "Sleep in: "
fi
echo -e "\n *------------------------------* "
barCounter=0;
counter=0
((timeBarSize=$shutDown * 2))
bar="||||||||||||||||||||||||||||||"
barEmpty=" "
((flag=0))
for ((i=shutDown*60;i>=0;i--));
do
if ((counter >= timeBarSize ))
then
((counter=0))
((barCounter=$barCounter + 1))
fi
((counter=$counter + 1))
((timehh=$i/3600))
((timemm=$i/60 - timehh*60))
((timess=$i - timemm*60 - timehh*3600))
if (( flag == 1 ))
then
echo $(tput cuu1)$(tput el)$(tput cuu1)$(tput el)$(tput cuu1)$(tput el)$(tput cuu1)$(tput el)$(tput cuu1)
fi
((flag=1))
echo -e " | $timehh:$timemm:$timess |"
echo -e "\r *------------------------------* "
echo -e "\r *${bar:0:$barCounter}${barEmpty:$barCounter:30}* "
echo -e "\r *------------------------------* "
sleep 1;
done
if [ $option -eq 1 ]
then
echo "Going to sleep..."
sleep 1
osascript -e 'tell application "System Events" to sleep'
elif [ $option -eq 0 ];
then
echo "Shutting down..."
sleep 1
osascript -e 'tell application "System Events" to shut down'
else
echo "No valid command found... doing nothing!"
fi
I also had to add this in my '/etc/sudoers' file (CAUTION, if you don't know how to handle this file! -> google):
# Custom privilege
myUser ALL=NOPASSWD: /Users/myUser/Documents/sleepTimer.sh

Resources