Infinite loop on yes/no ksh - bash

I have an annoying issue that seems to cause and infinite loop and I can't work out why. If I call the following function, it keeps repeating the yes/no options infinitely down the screen until I crash out.
AuditUpload() {
clear
echo "Audit report generated successfully"
echo " "
echo "Do you wish to upload qhub_audit.csv? (1 = Yes/2 = No):"
sleep 1
select yn in "Yes" "No"; do
case $yn in
Yes ) AuditUploader; Auditvi; exit;;
No ) echo "Upload cancelled"; Auditvi; exit;;
esac
done
}
I put the sleep in to see if it would remedy the issue but it still does the same. This issue seems to be very intermittent and doesn't happen every time. This script is written in korn shell (ksh).
AuditUploader function:
AuditUploader() {
echo "Uploading qhub_audit.csv to $HOST..."
curl -v -T qhub_audit.csv -# ftp://xxxxxxxx:xxxxxxxxx#xxxxxxxxxxxxx.com/
if [ "$?" -ne "0" ]
then
echo "ERROR: Cannot upload qhubload.csv"
exit
else
clear
echo "qhub_audit.csv has been put on $HOST successfully"
tput cup 5 5
echo "Copy and paste this link into internet explorer to download:"
tput cup 7 5
echo "ftp://xxxxxxxx:xxxxxxxxx#xxxxxxxxxxxxx.com/qhub_audit.csv"
read LINK
fi
}
Auditvi function:
Auditvi() {
clear
echo "Do you wish to view qhub_audit.csv? (1 = Yes/2 = No):"
sleep 1
select yn in "Yes" "No"; do
case $yn in
Yes ) vi qhub_audit.csv; exit;;
No ) exit;;
esac
done
}

After a bit of playing around it looks like it was looping whenever the 'curl' command returned a specific error which stopped the kill $$ from working properly. I replaced kill $$ with exit 1 and amended the other functions accordingly. I also put in a contingency to use kermit in case the FTP failed. Anyway, this is what my code looks like now:
#########################################
# Upload quotehub audit report function #
#########################################
AuditUploader() {
echo "Uploading qhub_audit.csv to $HOST..."
curl -v -T qhub_audit.csv -# ftp://$USER:$PASSWD#$HOST/ -m 10
if [ "$?" -ne "0" ]
then
echo "ERROR: Cannot upload qhubload.csv via FTP"
if [ ${term} = "tty1A" ]
then
echo "Attempting to download to modems server..."
wermit -s qhub_audit.csv
if [ $? -ne 0 ]
then
echo "Cannot upload to modems either!"
echo "This file will have to be downloaded manually"
exit 1
else
clear
echo "qhub_audit.csv has been put on modems server successfully"
tput cup 5 5
echo "Copy and paste this link into START -> RUN to download:"
tput cup 7 5
echo "\\\\\\xxxxxxxx\download\general\qhub_audit.csv"
read LINK
fi
else
echo "Upload failed!"
exit 1
fi
else
clear
echo "qhub_audit.csv has been put on $HOST successfully"
tput cup 5 5
echo "Copy and paste this link into internet explorer to download:"
tput cup 7 5
echo "ftp://$USER:$PASSWD#$HOST/qhub_audit.csv"
read LINK
fi
}
#######################################################
# Function to prompt user to upload qhub audit report #
#######################################################
AuditUpload() {
clear
echo "Audit report generated successfully"
echo ""
echo "Do you wish to upload qhub_audit.csv? (y/n):"
read REPLY
case "$REPLY" in
Y) AuditUploader; Auditvi; exit;;
y) AuditUploader; Auditvi; exit;;
N) Auditvi; exit;;
n) Auditvi; exit;;
*) echo "invalid option";;
esac
}
######################################
# Function to view qhub audit report #
######################################
Auditvi() {
if [ "$?" -ne "0" ]
then
exit 1
else
clear
echo "Do you wish to view qhub_audit.csv? (y/n):"
read REPLY
case "$REPLY" in
Y) vi qhub_audit.csv; exit;;
y) vi qhub_audit.csv; exit;;
N) exit;;
n) exit;;
*) echo "invalid option"; Pause; Auditvi;;
esac
fi
}
Thanks again guys for all your help.

Related

Bash script to chose based on user input

Problem:
I need to make this bash script to choose based on the user inputs. Example how can i add choices? such that user just select from 1 to 3 and that is set in variable CLUSTER_NAME.
choices are test.com, try.com and me.com
Script
#!/bin/bash
sops_ops() {
sops --version
if [ "$?" -eq "0" ]; then
echo "proceed sops ops"
else
echo "check sops binary"
fi
read -p 'Enter cluster_NAME: = ' CLUSTER_NAME
test_environment="test.com"
test1_environment="test1.com"
test2_environment="test2.com"
case "${$CLUSTER_NAME}" in
prod.$test_environment) ;;
dev.$test1_environment) ;;
stage.$test2_environment) ;;
test.$test_environment) ;;
*) echo "Invalid option: ${CLUSTER_NAME}" 1>&2 && exit 1 ;;
if [ $CLUSTER_NAME = test.$test_env ];then
printf "got cluster $CLUSTER_NAME"
elif [ $CLUSTER_NAME = "test.test.com" ];then
printf "got dev cluster $CLUSTER_NAME"
echo "not found cluster"
else
echo "Environment not available"
fi
}
sops_ops
Question:
How do I do that?
Any help is appreciated!

Updating sub-menus variables

I have a problem with this bash script:
#!/bin/bash
G=100
echo $G
main_menu()
{
while :
do
clear
echo "Select from menu"
echo "[1] Press 1 to show savings"
echo "[2] Press 2 to withdraw savings"
echo "[3] Press 3 to exit"
echo "Enter your menu choice [1-3]: \c "
read -r m_menu
case "$m_menu" in
1) option_1;;
2) option_2;;
3) exit 0;;
*) echo "\nERROR: Please select a valid menu choice";
echo "Press ENTER To Continue..." ; read ;;
esac
done
}
option_1()
{
clear
echo "Your balance is $G"
echo "\nPress ENTER to return to menu..."
read
return
}
option_2()
{
clear
echo "Withdraw savings"
read -rp "Enter amount to withdraw: " num
if [ $num -le $G ]; then
answer=$(echo $(( G - num )))
echo "Your new balance is: $answer"
echo "$answer" | tee "$G"
elif [ $num -gt $G ]; then
echo "No: not eough money in your balance"
fi
read
return
}
main_menu
The problem is the following: how do I make sure that once I withdraw savings, my saving count will be updated? Because if I withdraw $90, obviously when I return to the balance it should be $10 and yet this doesn't work for me (it still says saving balance is $100)
What can I do?
Thank you (sorry for my poor English)
You have to update G in your code.
if [ $num -le $G ]; then
G=$(( G - num ))
echo "Your new balance is: $G"

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.

Shell Script with If, Select and Case

Can anyone advise how to edit this script to perform the following:
If folder exists - "then are you sure you want to uninstall?"
If yes - perform file copying, if not then stop script.
Else - can't find folder, stop script.
if [ -e "/tmp/installpackage" ]
then
echo "Are you sure you want to uninstall?"
select yn in "Yes" "No"; do
case $yn in
Yes )
echo "Beginning uninstall...";
cp file1.txt original/path/location;
break;;
No )
echo "Stopping uninstall.";
exit 1;;
esac
done
else
echo "Can't find the folder, package not isntalled."
exit 1
fi
Your code works as expected. But you have to enter 1 or 2 and not yes or no.
However I would change the first line to:
if [ -d "/tmp/installpackage" ]
-d tests whether the file exists and is a directory
I think after the line esac you want a exit otherwise you have a infinite loop to ask you for answers
try
if [ -d "/tmp/installpackage" ]
then
echo "Are you sure you want to uninstall?"
select yn in "Yes" "No"; do
case $REPLY in
Yes )
echo "Beginning uninstall...";
cp file1.txt original/path/location;
break;;
No )
echo "Stopping uninstall.";
exit 1;;
*)
echo "Incorrect choice";
break;;
esac
done
else
echo "Can't find the folder, package not installed."
exit 1
fi
I would try testing for bail out conditions first then fall through to the uninstall code:
[ ! -d '/tmp/installpackage' ] && \
echo "Can't find the folder, package not isntalled." && exit 1
echo -n 'Are you sure you want to uninstall? [y|n] '
read answer
[[ ! "$answer" = [Yy] ]] && echo 'Stopping uninstall.' && exit 1
echo 'Beginning uninstall...'
cp file1.txt original/path/location

unexpected fi in bash script

This is the script and I keep getting an unexpected fi error. What am I missing? .. (I started using [] for the if statement but since I'm using this command I deleted the [] .. Is it ok this way?)
if type "java" 2>&1;
then
echo "All ok . . . ";
exit
else
read -n1 -r -p "Yo need to install"
while true; do
echo "Want to install??"
select yn in "y" "n"; do
case $yn in
y ) echo "Installing here..."; break;;
n ) echo "Ok... stopping..."; exit;;
esac
done
exit
fi
thanks!
while ends with done, not exit. Try this:
if type "java" 2>&1;
then
echo "All ok . . . ";
exit
else
read -n1 -r -p "Yo need to install"
while true; do
echo "Want to install??"
select yn in "y" "n"; do
case $yn in
y ) echo "Installing here..."; break;;
n ) echo "Ok... stopping..."; exit;;
esac # <-- ending `case`
done # <-- ending `select`
done # <-- while ends with `done`, not `exit`!
fi # <-- ending `if`
You have an exit before the last fi; I suppose that should be a done.

Resources