Here is my code:
while [[ "$counter" -gt 0 ]];
do
startNewTest
echo -e "\n" | ./myscript.sh send
while :
do
sleep 30
echo -e "\n Reading status... \n"
./myscript.sh status | \
while read i
do
if echo $i | grep -q "$KEYWORD"
then
echo -e "\n Starting a new round of test... \n"
break 2
fi
done
done
let counter=counter-1
done
When the if condition is met, the "break 2" line should break 2 layers of loop, right? However, when i ran the script, it only break the inner-most loop, and stuck inside the infinite "while :" loop. Where did i make the mistake?
I also tried "break 3", didn't work either.
Can you test this with your myscript.sh ?
It seems you are breaking out of a subprocess after the pipe sign.
Getting the output in the while-loop without a subprocess might help:
while [[ "$counter" -gt 0 ]];
do
startNewTest
echo -e "\n" | ./myscript.sh send
while :
do
sleep 30
echo -e "\n Reading status... \n"
while read i
do
if echo $i | grep -q "$KEYWORD"
then
echo -e "\n Starting a new round of test... \n"
break 2
fi
done < <(./myscript.sh status)
done
let counter=counter-1
done
Related
I have written this code to imitate tail command without using inbuilt command and it is giving error in for loop though syntax is correct!
I am not able to figure it out where actually the error is?
Also Expected output:
It should print last n number of lines from the file.
n is scanned from user.
#!/bin/sh echo -n "Enter file name: " read file_name echo -n "Enter number of lines: " read n touch $file_name str="end" temp="temp" echo "Start entering data of file and write end for stopping: " while [ 1 ] do read string touch $temp echo $string > $temp grep -w "$str" $temp if [ $? -eq 0 ] then break else cat $temp >> $file_name fi done rm $temp echo "---------------------------------------------------------" total_lines= wc -l < $file_name echo $total_lines a=expr $total_lines - $n exec < $file_name for ((i=$a;i<$total_lines;i++ )) do read a1 echo $a1 done
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.
I have a bash script that asks the user for their details.
I'm setting a limit to how long we wait for the input. I've found this and it appears to what I want.
timelimit=5
echo -e " You have $timelimit seconds\n Enter your name quickly: \c"
name=""
read -t $timelimit name
#read -t $timelimit name <&1
# for bash versions bellow 3.x
if [ ! -z "$name" ]
then
echo -e "\n Your name is $name"
else
echo -e "\n TIME OUT\n You failed to enter your name"
fi
It shows "You have 5 seconds..." any way to update the output so it shows 4,3,2,1 etc as it counts down ?
Thanks
I have tried most of these answers and none of them worked perfectly for me.
Been playing with this for a local developer deployment script.
This solves a few of the issues noted, like including printed output, etc.
Also wrapped as a function for portability. I'm keen to see any improvements.
Here is my solution:
#!/bin/bash
# set -euo pipefail
READTIMEOUT=5
function read_yn {
MESSAGE=$1
TIMEOUTREPLY=$2
NORMALREPLY="Y"
if [ -z "${TIMEOUTREPLY}" ]; then
TIMEOUTREPLY="Y"
fi
TIMEOUTREPLY_UC=$( echo $TIMEOUTREPLY | awk '{print toupper($0)}' )
TIMEOUTREPLY_LC=$( echo $TIMEOUTREPLY | awk '{print tolower($0)}' )
if [ "${TIMEOUTREPLY_UC}" == "Y" ]; then
NORMALREPLY="N"
fi
NORMALREPLY_UC=$( echo $NORMALREPLY | awk '{print toupper($0)}' )
NORMALREPLY_LC=$( echo $NORMALREPLY | awk '{print tolower($0)}' )
for (( i=$READTIMEOUT; i>=0; i--)); do
printf "\r${MESSAGE} [${NORMALREPLY_UC}${NORMALREPLY_LC}/${TIMEOUTREPLY_UC}${TIMEOUTREPLY_LC}] ('${TIMEOUTREPLY_UC}' in ${i}s) "
read -s -n 1 -t 1 waitreadyn
if [ $? -eq 0 ]
then
break
fi
done
yn=""
if [ -z $waitreadyn ]; then
echo -e "\nNo input entered: Defaulting to '${TIMEOUTREPLY_UC}'"
yn="${TIMEOUTREPLY_UC}"
else
echo -e "\n${waitreadyn}"
yn="${waitreadyn}"
fi
}
read_yn "TESTING" "y"
GIST: https://gist.github.com/djravine/7a66478c37974940e8c39764d59d35fa
LIVE DEMO: https://repl.it/#DJRavine/read-input-with-visible-countdownsh
This should work and shouldn't overwrite input, bit more long winded than the other solutions.
#!/bin/bash
abend()
{
stty sane
exit
#Resets stty and then exits script
}
DoAction(){
stty -echo
#Turn off echo
tput sc
#Save cursor position
echo -ne "\033[0K\r"
# Remove previous line
tput cuu1
#Go to previous line
tput el
#clear to end of line
echo "You have $(($time-$count)) seconds"
#Echo timer
echo -n "$Keys"
#Echo currently typed text
stty echo
#turn echo on
tput rc
#return cursor
}
main()
{
trap abend SIGINT # Trap ctrl-c to return terminal to normal
stty -icanon time 0 min 0 -echo
#turn of echo and set read time to nothing
keypress=''
time=5
echo "You have $time seconds"
while Keys=$Keys$keypress; do
sleep 0.05
read keypress && break
((clock = clock + 1 ))
if [[ clock -eq 20 ]];then
((count++))
clock=0
DoAction $Keys
fi
[[ $count -eq $time ]] && echo "you have run out of time" && abend
done
stty sane
echo Your username was $Keys
echo "Thanks for using this script."
exit 0
}
main
This seems to work:
$ cat test.sh
total=5 # total wait time in seconds
count=0 # counter
while [ ${count} -lt ${total} ] ; do
tlimit=$(( $total - $count ))
echo -e "\rYou have ${tlimit} seconds to enter your name: \c"
read -t 1 name
test ! -z "$name" && { break ; }
count=$((count+1))
done
if [ ! -z "$name" ] ; then
echo -e "\nyour name is $name"
else
echo -e "\ntime out"
fi
#!/bin/bash
timelimit=6
name=""
for (( i = 1 ; i <= $timelimit; i++ )); do
echo -ne "\rYou have $(expr $timelimit - $i) seconds. Enter your name quickly: \c"
[ ! -z "$name" ] && { break ; }
read -t 1 name
done
if [ -z "$name" ]; then
echo -e "\n TIME OUT\n You failed to enter your name"
else
echo -e "\n Your name is $name"
fi
this should work
This works fine and fast for me:
#!/bin/bash
#Sets starttimestamp
starttime=$(date +%s)
#Sets timeout
timeout=5
#sets successflag default to false
success=false
#Save Cursorposition
echo -n -e "\033[s"
#While time not up
while [ $(($starttime+$timeout)) -gt $(date +%s) ] ; do
#Return to saved Cursorpositon
echo -n -e "\033[u"
#Display time left
echo "$(((starttime+timeout)-$(date +%s))) seconds left"
#Ask for 1 char then go on in loop make it look like an ongoing input by adding the user variable to the prompt
if read -p foo="Username: $user" -n 1 -t 1 c ; then
#If user hits return in time c will be empty then break out of loop and set success true
if [[ $c == "" ]] ; then
success=true
break
fi
# Append latest character to user variable
user=${user}${c}
unset c
fi
done
if $success ; then
echo "Yiha!"
else
echo "Too late!"
fi
I'm trying to keep a external counter in my bash script.
As most of the script is specific to what it's for, I'm only going to insert the pertinent parts that I can't seem to get working. Everything before does get defined. Also before someone comments about the cat, I tried (< $TMPFILE) as well. The issue appears to be not writing to the file.
#!/bin/bash
TMPFILE="/tmp/nettestnum"
if [ -e "$TMPFILE" ]; then I=$(cat $TMPFILE); else I="1"; fi
nettest_start() {
grep -q "/root/bin/nettest" /etc/rc.local
if [ $? -eq 1 ]; then
sed -i 's|touch /var/lock/subsys/local|touch /var/lock/subsys/local \&\& /root/bin/nettest|' /etc/rc.local 2>&-
echo "Script started at $DATEVAL" >> "$LOGFILE" 2>&1
echo "Script will run every $TIMELb minutes, $LIMIT times"
touch "$TMPFILE"
nettest_run
else
echo "Nettest is already started and will relaunch upon next reboot"
fi
}
nettest_run() {
echo "$DATE : Starting scan" >> "$LOGFILE" 2>&1
#
while [[ "$I" -lt "$LIMIT" ]]
do
echo "$DATE : Starting scan" >> "$LOGFILE" 2>&1
#
HOSTS="$(...)"
for myHost in $HOSTS
do
PING=$(ping -f -c $COUNT "$myHost" |grep 'rtt' | awk '{print $4}')
echo "$myHost / $PING" >> "$LOGFILE" 2>&1
done
echo "$DATEVAL : Finished" >> "$LOGFILE" 2>&1
echo "$DATEVAL : Netstat Start" >> "$STATLOG" 2>&1
netstat -s |egrep -i "dropped|loss|reject|timeout|invalid" >> "$STATLOG" 2>&1
echo "$DATEVAL : Netstat Finished" >> "$STATLOG"G 2>&1
echo "." >> "$LOGFILE" 2>&1
sleep "$TIMEL"
let I++ || true
set +C
echo "$I" > "$TMPFILE"
done
}
Edit 4: re-added } and showing both functions.
I also need to figure out how to write an exit for the loop, but I'm pretty sure that's just a [ $? = 0 ]
Edit:
An example of some of the output I'm seeing when I run a status command (built into the script)..
Nettest is enabled on startup
PID number: 6059
Nettest is actively running in memory
On iteration of 100
iteration shows 1 on the first run.
Edit 2: redid the sample with full example, minus customized commands.
In the end, I got it working by adding 2>&1 to the line needed.
echo "$I" > "$TMPFILE" 2>&1
Try this:
if [ -e "$TMPFILE" ]; then I=`cat $TMPFILE`; else I=1; fi
while [[ $I -lt $LIMIT ]]
A while loop creates a subshell, with a copy of all your current variables.
#!/bin/bash
I=1
CHECK=1 # boolean for demonstration
while CHECK; do
let I++
CHECK=0
done
echo $I # prints 1, not two
This happens because the while subshell gets a copy of the I variable, which it increments. Once the subshell exits, the original variable comes back.
Your I variable is being incremented, and acting as your loop counter. I expect this is causing you all kinds of problems for properly ending your loop, and having other bits of this program see the "right" variable. I see no reason you could not replace the while loop with an equivalent for loop, and avoid all of these problems entirely.
I try to validate an email with a shell script. Is there a easy example to validate a mail? Asked google but just found crap and PHP (also crap..).
Thanks and regards.
If you explicitly state bash on the #! line, you can uses regexes:
#!/bin/bash
if [[ $email =~ '(.+)#(.+)' ]] ; then
user=${BASH_REMATCH[1]}
host=${BASH_REMATCH[2]}
fi
If you are serious about programing with bash, read the man page all the way through. Twice. Also read the Bash FAQ.
Validate script.
The meaning of this script, is to be sure from all emails that are valid or not before sending them email.
this script check a list of emails.
#!/bin/bash
#:
#: e-mail.verify.sh
#:
#: Date: 2011/14/12 13:14 PM IST
#: Author: Louay _at_ louie.msh#gmail.com
#: Discription: Verify (or) Validate the Hotmail Adresses.
#:
#:
#: First we create a Expect script to be sourced for us.
if [ ! $# == 1 ]
then
echo "Invalid Args $0 Filename"
exit 0
fi
#: Verifying the Hotmail adressess.
#: First verify the network Connections
C_R="\e[01;31m" ## Colors
C_B="\e[01;30m"
C_G="\e[01;32m"
C_END="\e[00m"
SMTPSERV=`host -t mx hotmail.com |grep 5 | grep mx2.hotmail.com |cut -d " " -f 7| sed 's/\.$//'`
ping -c2 $SMTPSERV >/dev/null
if [ "$?" -eq 0 ]
then
echo -e "Internet Connection" "\t\t\t\t\t\t$C_G[ OK ]$C_END"
echo -e "$SMTPSERV is AVAILABLE."
echo -n "Verifing"
for (( i=0; i<5; i++ ))
do
echo -n ".."
sleep 1
done
echo
else
echo -e "Internet Connection:" "\t\t\t\t\t\t$C_R[ FAIL ]$C_END" ""
echo -e "$SMTPSERV is Unavialable."
echo -e "Check your Network settings."
exit 0
fi
COUNT=0
RM_FILE="validemails.txt"
rm -f $RM_FILE
cat $1 | while read LINE; do
{
MAFR="MAIL FROM: <louie.msh#gmail.COM>"
MATO="RCPT TO: <$LINE>"
#: ^variablies declared for not get escaped in the next cat command, where
#: we set the $MAFR in the expect script.
cat << __EOF > e-veri
#!/bin/expect
#:
#: Date: 2011/14/12 01:14 PM
#: Author: Louay Mshelim_at_ louie.msh#gmail.com
#: Discription: Expect Script to Verify/Validate the Hotmail Adresses.
#:
set VMAFR "$MAFR"
set VMATO "$MATO"
spawn nc -C mx4.hotmail.com 25
expect "Sending"
send "HELO mx4.hotmail.com\r"
expect "OK"
send "\$VMAFR\r"
expect "OK"
send "\$VMATO\r"
expect "250"
send "quit\r"
expect eof
__EOF
#: Running the expect script and extracting the Results.txt
expect e-veri > Results.txt
grep 550 Results.txt >/dev/null
if [ "$?" -eq 0 ]
then
echo -e $LINE >> invalid.txt #invalid E-mails
else
echo -e "$LINE" >> validemails.txt
fi
}
done
echo -e "Valid E-mail have been saved to $C_R[ validemails.txt ]$C_END"
#: END
Here is an improved and working version of the script by codevour:
#!/bin/bash
# check for valid usage
if [ x$1 = 'x' ]
then
echo "Usage: $0 <email address>"
exit 1
fi
mailcmd=`mktemp`
# grabbing fields
user=`echo $1 | perl -p -e 's/^([^#]+)#([^\#]+)$/$1/g'`
host=`echo $1 | perl -p -e 's/^([^#]+)#([^\#]+)$/$2/g'`
mxhost=`host -t mx $host|perl -p -e 's/.* ([^ ]+)\.$/$1/g'|sort -R|tail -1`
# compose email commands
echo -ne "helo example.com\r\n" > $mailcmd
echo -ne "mail from: <tester#example.com>\r\n" >> $mailcmd
echo -ne "rcpt to: <$1>\r\n" >> $mailcmd
echo -ne "quit\r\n" >> $mailcmd
# check for mail results
mailresult=`cat $mailcmd | nc $mxhost 25| grep ^550 | wc -c`
if [ $mailresult -eq 0 ]
then
echo $1 "is valid"
exit 0
else
echo $1 "is not valid"
exit 1
fi
# clean up
rm $mailcmd
You mean something like this?
#!/bin/bash
# check for valid usage
if [ x$1 = 'x' ]
then
echo "Usage: $0 <email address>"
exit 1
fi
# grabbing fields
user=`echo $1 | cut -f1 -d\#`
host=`echo $1 | cut -f2 -d\#`
mxhost=`host -t mx $host | cut -f7 -d\ `
len=`echo $mxhost | wc -c`
len=`expr $len - 2`
mxhost=`echo $mxhost | cut -b1 -$len`
# compose email commands
echo -ne "helo test.com\r\n" > mailcmd
echo -ne "mail from: test\#test.com\r\n" >> mailcmd
echo -ne "rcpt to: $1\r\n" >> mailcmd
echo -ne "quit\r\n" >> mailcmd
# check for mail results
mailresult=`cat mailcmd | nc $mxhost 25| grep ^550 | wc -c`
if [ $mailresult -eq 0 ]
then
echo $1 "is valid"
exit 0
else
echo $1 "is not valid"
exit 1
fi
# clean up
rm mailcmd
Found at:
Fun things in Life - Simple Bash Email Validator
My any suggestion for the latter script, check work with multiple servers that accept checks without authentication, using nslookup who knows:
For example code in:
http://www.vivaolinux.com.br/script/Simples-Verificador-de-Email-Gmail
see the code below in the site.
I hope I have contributed and I hope to collaborate as well.
Thank you.
You can use like this,
read emailId
if echo "${emailId}" | grep '^[a-zA-Z0-9]*#[a-zA-Z0-9]*\.[a-zA-Z0-9]*$' >/dev/null; then
echo Valid
else
echo Not Valid
fi