I have written a script containing various user queries and conditions. First, I want the user to be asked if the changelog should be displayed. Then the user is asked if he should do the update. But here is the problem, after the first condition and the display of the changelog, the next query is simply skipped. Why is that?
if version_gt $serverversion $version; then
echo -e "\e[34m#########################################################"
echo -e "\e[34mThere is a new version. Do you want to see the Changelog?"
echo -e "\e[34m#########################################################"
read -p "Yes(y)/No(n) " -n 1 -r changelog
if [[ $changelog =~ ^[Yy]$ ]]
then
curl --silent "$changelogurl"
fi
echo -e "\e[34m#########################################################"
echo -e "\e[34mDo you want to update?"
echo -e "\e[34m#########################################################"
read -p "Yes(y)/No(n) " -n 1 -r update
if [[ $update =~ ^[Yy]$ ]]
then
echo -e "\e[32m#########################################################"
echo -e "\e[32mI am updating myself..."
echo -e "\e[32m#########################################################"
sleep 4
curl --silent "$bashlyurl" > bashlyblog.sh
curl --silent "$templateurl" > template.html
echo -e "\e[32m#########################################################"
echo -e "\e[32mUpdate done. Restart..."
echo -e "\e[32m#########################################################"
/bin/bash bashlyblog.sh
exit 1
fi
fi
You might be typing the letter y and pressing Enter key whereas your script moves on as soon as you've typed y, since you added -n 1 to your read command.
Try typing y without pressing Enter key, or removing -n 1 if you'd rather press key Enter.
Related
How can I use bash to scan for a specific string of characters in a text file and then use an if then statement to execute a specific command depending on the string?
I am trying to use rsync to back up some raspberry pis from a query string output from an HTML form. I have minimal bash experience and I have been poking and prodding this code for days now and I would love for some advice.
QUERY_STRING will contain something similar to "Backup_To_Comp=tasting-side_backup&subbtn=Submit" with the "Tasting-side_backup" being swapped for other radial button tags as selected.
#!/bin/bash
echo "Content-type: text/html"
echo ""
echo "$QUERY_STRING" > /var/www/cgi-bin/scan.txt
BackupToCompFrom=`echo "$QUERY_STRING" | sed -n 's/^.*Backup_To_Comp=\([^&]*\).*$/\1/p' | sed "s/%20/ /g"`
echo "<html><head><title>What You Said</title></head>"
echo "<body>Here's what you said:"
echo "You entered $BackupToCompFrom in from field."
sleep 1
file="/var/www/cgi-bin/scan.txt"
##echo "$QUERY_STRING"
while IFS='' read -r line || [[ -n "$line" ]];
do
if [[ $line = "tasting-side_backup" ]]; then
echo "GotIt."
rsync pi#192.168.1.1:/home/pi/screenly_assets /home/pi/Downloads
elif [[ $line = "~tasting-main"* ]]; then
print "Tasting Main"
elif [[ $line = "~lodge"* ]]; then
print "Lodge"
elif [[ $line = "~barn"* ]]; then
print "Barn"
else
print "Please select a pi to copy from!"
fi
done
How can I use bash to scan for a specific string of characters in a text file and then use an if then statement to execute a specific command depending on the string?
You can use a command in the if statement. Now the exit code for that command is used to determine true or false. For simple searching of a query to a file, you can use grep.
if grep -q "$QUERY_STRING" file; then
The -q is used to prevent any output from grep ending up in stdin.
I am trying to implement confirmation prompt with a bash script but for some reason, prompt won't wait for user input. I've tried many examples but no luck so far. I am on MacOS if it makes any difference.
Just a few examples I tried (All copy+paste from other answers in SO):
#!/bin/bash
read -p "Are you sure? " -n 1 -r
echo # (optional) move to a new line
if [[ $REPLY =~ ^[Yy]$ ]]
then
# do dangerous stuff
fi
#!/bin/bash
read -p "Continue (y/n)?" CONT
if [ "$CONT" = "y" ]; then
echo "yaaa";
else
echo "booo";
fi
#!/bin/bash
while true; do
read -rsn1 input
if [ "$input" = "a" ]; then
echo "hello world"
fi
done
#!/bin/bash
read -p "Continue (y/n)?" choice
case "$choice" in
y|Y ) echo "yes";;
n|N ) echo "no";;
* ) echo "invalid";;
esac
This doesn't even prompt anything:
#!/bin/bash
read -n 1 -s -r -p "Press any key to continue"
Changed to answer from comment : in commit-msg hook it seems standard input is closed, indeed this can be checked adding following command
ls -l /dev/fd/
which gives
... 0 -> /dev/null
as mentioned in this post
exec 0< /dev/tty
will restore standard input to tty, another solution as noticed standard output and error are still redirected to tty
exec 0<&1
The original question has the important part missing and it is my fault not making it very clear in very first place. It became apparent after #NahuelFouilleul's comment. The confirmation/question prompt was not waiting for user to hit a key. The reason was because my bash script was being called by a git hook. Things seem to be done in slightly different way in such cases. The solution is below but the original answer is here.
#!/bin/bash
exec < /dev/tty
while true; do
read -p "Accepting the offer? (y/n) " answer
if [[ $answer =~ ^[Yy]$ ]] ;
then
echo "Accepted"
else
echo "Not accepted"
fi
break
done
Try this:
echo -n "Continue (y/n)?"
read CONT
if [ "$CONT" = "n" ]
then
echo "NO"
else
echo "YES"
fi
the echo -n means no newline
I made this bash script but getting this error when running it: ./admin2.sh: line 78: syntax error near unexpected token else'
./admin2.sh: line 78:else'.
I've edited it many times but i cant seem to find what exactly the error is. this is the script:
#!/bin/bash
if [[ $key == 1029127 ]]
clear
echo -e ""
echo -e -n "${LIGHTRED}[!] ${WHITE}Loading admin menu"
spinner () {
local SP_WIDTH="$3"
local SP_DELAY="$4"
local SP_STRING=${2:-"'|/=\'"}
local SP_COLOR=0
tput civis
while [ -d /proc/$1 ]; do
((RANDOM%2 == 0)) && SP_COLOR=3$((RANDOM%8)) ||
SP_COLOR=9$((RANDOM%8))
printf "\e[1;${SP_COLOR}m\e7 %${SP_WIDTH}s \e8\e[0m" "$SP_STRING"
sleep ${SP_DELAY:-.2}
SP_STRING=${SP_STRING#"${SP_STRING%?}"}${SP_STRING%?}
done
tput cnorm
}
sleep 2.5 &
spinner "$!" '-\\|/' '1.1' '.2'
tput civis
sleep 1
tput cnorm
while true
do
clear
echo -e "${LIGHTCYAN} Welcome"
echo -e ""
echo -e -n "${WHITE}- Current IP:${LIGHTRED} "
w|awk '{if(NR>2){print $3}}' $3
echo -e -n "${WHITE}- Users connected:${LIGHTRED} "
users | wc -w
echo -e "${WHITE}- Admin privileges:${WHITE
[${LIGHTGREEN}Enabled${WHITE}]"
echo -e ""
echo -e "${LIGHTRED} //Announcements//"
echo -e ""
echo -e "${YELLOW}- Type: /help to see commands"
echo -e "\n"
echo -e ""
echo -e ""
echo -e -n "${LIGHTRED}Type: \c"
read answer
else
echo -e ""
echo -e "${LIGHTRED}[!] ${WHITE}Incorrect key, access denied.
fi
You also seem to have forgotten to end the second while loop. You should end it by adding a doneon the line before the else
...
read answer
done
else
echo -e ""
echo -e "${LIGHTRED}[!] ${WHITE}Incorrect key, access denied.
fi
You're missing a then after your if statement on line 2:
if [[ $key == 1029127 ]]
then
...
else
...
fi
Many people prefer to put the then on the same line, as:
if [[ $key == 1029127 ]]; then
...
else
...
fi
Either way I'd encourage you to properly indent your code so that it's easier to read, and be consistent about style choices such as putting then and do on separate lines or not.
For some reason commands are not running after the first if statement.
"/usr/local//backup.sh: sleep: not found" for example..
The first if statement goes like:
if [ "$command" == "start -c" ]; then
echo -e "${ORANGE}Starting website backup...${E}"
sleep 1
DT=`date +%Y-%m-%d`
echo -e "${ORANGE}Started backup at $DT ${E}"
sleep 1
tar -zcvf web-$DT.tar.gz /usr/local/www/nginx
echo -e "${ORANGE}Compatced files, moving to backup directory${E}"
sleep 1
mv web-$DT.tar.gz $PATH/web-$DT.tar.gz
echo -e "${CYAN}Moved to backups ($PATH/web-$DT.tar.gz)\nDo you want to upload to ftp?${E}\n${CYAN} 'y' or 'n'?${E}"
read answer
if [ "$answer" == "y" ]; then
echo -e "${ORANGE}Uploading to ftp server...${E}"
sleep 1
if ftp -in -u ftp://$USER:$PASS#$HOST/Backups/f $PATH/web-$DT.tar.gz; then
echo -e "${GREEN}Uploaded! Bye!${E}"
else
echo -e "${ORANGE}Couldn't upload with ftp command, trying with curl...${E}"
sleep 1
curl -T "$PATH/web-$DT.tar.gz" -u $USER:$PASS ftp://$HOST/Backups/f/
echo -e "${GREEN}Uploaded! Bye!${E}"
fi
else
echo -e "${GREEN}Bye!${E}"
fi
Everything works fine inside this statement, however, after the elif compassion it just doesn't.
Here's the problematic code:
elif [ "$command" == "start -d" ]; then
echo -e "${ORANGE}Starting database backup...${E}"
sleep 1
DT=`date +%Y-%m-%d`
echo -e "${ORANGE}Started backup at $DT ${E}"
sleep 1
umask 177
echo -e "${ORANGE}Dumping database 'account'\n${E}"
mysqldump --user=$DBUSER --password=$DBPASS --host=$HOST account > $PATH/account-$DT.sql
sleep 1
echo -e "${ORANGE}Dumping database 'game'\n${E}"
mysqldump --user=$DBUSER --password=$DBPASS --host=$HOST game > $PATH/game-$DT.sql
sleep 1
echo -e "${ORANGE}Dumping database 'forum'\n${E}"
mysqldump --user=$DBUSER --password=$DBPASS --host=$HOST forum > $PATH/forum-$DT.sql
sleep 1
echo -e "${CYAN}Moved to backups ($PATH/<database-date>.sql)\nDo you want to upload to ftp?${E}\n${CYAN} 'y' or 'n'?${E}"
read answer
if [ "$answer" == "y" ]; then
echo -e "${ORANGE}Uploading to ftp server...${E}"
sleep 1
curl -T "$PATH/account-$DT.sql" -u $USER:$PASS ftp://$HOST/Backups/f/Databases/
curl -T "$PATH/game-$DT.sql" -u $USER:$PASS ftp://$HOST/Backups/f/Databases/
curl -T "$PATH/forum-$DT.sql" -u $USER:$PASS ftp://$HOST/Backups/f/Databases/
sleep 1
echo -e "${GREEN}Uploaded! Bye!${E}"
else
echo -e "${GREEN}Bye!${E}"
fi
and then I just ended it..
else
echo -e "${RED}Sorry! Not found${E}"
fi
As you can see there's spaces in the if statements and all of that, so what's wrong with this??
I've the #!/bin/bash up top as well, all the variables exist too.
You seem to have overwritten the value of the PATH variable at some point in your code. The shell needs that variable in order to know where to find programs like sleep (Hence the "not found" error). Name your path variable something else.
I have a script that runs flawlessly on many of the servers required. But recently it's failed on servers with old ksh versions.
Can you help me fix the offending line:
#!/bin/ksh
SUCCESS=0
FAILURE=0
while read IP
do
CURL=$(curl -s -m 2 -x http://$IP -L http://icanhazip.com)
if [[ "${IP%%:*}" == "${CURL%%:*}" ]] ; then
SUCCESS=$[SUCCESS+1]
echo "$IP ✓"
else
FAILURE=$[FAILURE+1]
echo "$IP X"
fi
done < <(curl -sL vpn-proxy-list.txt);
echo "✓: $SUCCESS X: $FAILURE"
The final line returns:
line 3: syntax error at line 14: `<(' unexpected
Unfortunately I'm unable to update ksh.
Can you help me make the done < <(curl -sL vpn-proxy-list.txt); portion simply work in bash? Or compatible with older versions (1993) of ksh?
You don't appear to be doing anything in the while body that cause trouble if it was run in a subshell, so I'd just stick with a plain pipline:
#!/bin/ksh
curl -sL vpn-proxy-list.txt | while read -r ip; do
output=$(curl -s -m 2 -x "http://$ip" -L http://icanhazip.com)
if [[ "${ip%%:*}" == "${output%%:*}" ]]; then
echo "$ip Y"
else
echo "$ip X"
fi
done
Now you're asking something that breaks because you're making variable changes in a subshell, and those variables disappear when the subshell exits. A workaround: use grouping braces
curl -sL vpn-proxy-list.txt | {
success=0
failure=0
while read -r ip; do
output=$(curl -s -m 2 -x "http://$ip" -L http://icanhazip.com)
if [[ "${ip%%:*}" == "${output%%:*}" ]]; then
echo "$ip Y"
let success+=1
else
echo "$ip X"
let failure+=1
fi
done
echo there were $success successes
echo there were $failure failures
}
# variables "success" and "failure" don't exist here.
You could make use of named pipes.
mkfifo foobar
curl -sL vpn-proxy-list.txt > foobar &
# Maybe sleep for a while here
while read -r IP; do
# do something here
done < foobar
rm foobar