Problem with using time check with if statments - BASH - bash

I am currently checking a .sh script just to do some basic things.
chmod +x catbash.sh
echo 'Hello, Please Enter your User Name'
echo
read VarUserName
currenttime=$(date +%H:%M)
if [[ $currenttime > 11:59 ]] || [[ $currenttime < 12:00 ]];
then echo 'Good Morning' $VarUserName'.'
fi
if [[ $currenttime > 12:00 ]] || [[ $currenttime < 16:59 ]];
then echo 'Good Afternoon' $VarUserName'.'
fi
if [[ $currenttime > 17:00 ]] || [[ $currenttime < 19:59 ]];
then echo 'Good Evening' $VarUserName'.'
fi
if [[ $currenttime > 20:00 ]] || [[ $currenttime < 23:59 ]];
then echo 'Good Night' $VarUserName'.'
fi
My issue is that i am trying to use the systems current time to be used in a if statement and depending on the time for a different output.
right now the script outputs all all of the "good...." echos and does not output a single echo depending on the time.
thank you for the help.

The problem is with your conditions, all of them permit any given value, did you maybe want to use && instead of ||?

It would be much simpler if you would write it using the elif construction and start from the later times and work your way down.
chmod +x catbash.sh
currenttime=$(date +%H:%M)
if [[ "$currenttime" > "19:59" ]]; then echo "Good Night ${USER}"
elif [[ "$currenttime" > "16:59" ]]; then echo "Good Evening ${USER}"
elif [[ "$currenttime" > "11:59" ]]; then echo "Good Afternoon ${USER}"
elif [[ "$currenttime" > "05:59" ]]; then echo "Good Morning ${USER}"
else echo "Good Night ${USER}"

Related

"If" statement with "and" operator - daytimes

I have issues with the last if in this example:
#!/bin/bash
sunrise="05:00:00";
currenttime=$(date -u +%H:%M:%S);
sunset="18:00:00"
if [[ "$sunrise" < "$currenttime" ]] ; then
echo works1;
fi
if [[ "$sunset" > "$currenttime" ]] ; then
echo works2;
fi
# during the day:
if [[ "$sunrise" < "$currenttime" ]] && [[ "$currenttime" > "$sunset" ]] ; then
echo works3;
fi
I get the output of the first two echo but not from the last one.
What am I doing wrong?
Of course I'm doing this tests now at 11:30.
If current time is 11:30, then 11:30 is smaller than 18:00 so the last condition of script is false.
Just to make this answer a bit more useful, you can use set -x to print all the steps that the script does which helps to find this kind of bugs.
And also, use "seconds from epoch" when working with time and transform them back at the end of the script: working with integer is much easier and safer than working with strings.
I suspect you want this:
if [[ "$currenttime" <= "$sunrise" ]] ; then
echo "before sunrise"
fi
if [[ "$currenttime" >= "$sunset" ]] ; then
echo "after sunset"
fi
if [[ "$sunrise" < "$currenttime" && "$currenttime" < "$sunset" ]] ; then
echo "daytime"
fi

How to properly report if X & ( Y<1 or Z>2 )

I need some help with the script below, everything fails when it comes to third elif. I tried both < and -lt, both fail. I don't know what to do anymore
#!/bin/bash
currenttime=`date +%H%M`
morning="1800"
evening="2000"
host=127.0.0.1
while true; do
ping -c 1 -w 5 $host &> /dev/null
if [[ $? != 0 && ($currenttime > $evening || $currenttime < $morning) ]] #Ping down, and later than evening, or earlier than morning
then
echo -e "Ping down, later than evening, earlier than morning"
elif [[ $? != 2 && ($currenttime > $evening || $currenttime < $morning) ]] #Ping up, and (later than evening, or earlier than morning)
then
echo -e "Ping is up, later than evening, earlier than morning"
elif [[ $? != 0 && ($currenttime < $evening || $currenttime > $morning) ]] #Ping down, and (earlier than evening, or later than morning)
then
echo -e "Ping is down, and it is earlier than evening or later than morning"
elif [[ $? != 2 && ($currenttime < $evening || $currenttime > $morning) ]] #Ping up,and (earlier than evening, or later than morning)
then
echo -e "Ping is up and it is earlier than evening, or later than morning"
else
echo "WTF?"
fi
done
#!/bin/bash
currenttime=`date +%H%M`
morning="1800"
evening="2000"
host=127.0.0.1
while true; do
PINGOUTPUT=`ping -c 1 -w 5 $host &> /dev/null; echo $?`
if [[ $PINGOUTPUT != 0 && ($currenttime > $evening || $currenttime < $morning) ]] #Ping down, and later than evening, or earlier than morning
then
echo -e "Ping down, later than evening, earlier than morning"
elif [[ $PINGOUTPUT != 2 && ($currenttime > $evening || $currenttime < $morning) ]] #Ping up, and (later than evening, or earlier than morning)
then
echo -e "Ping is up, later than evening, earlier than morning"
elif [[ $PINGOUTPUT != 0 && ($currenttime < $evening || $currenttime > $morning) ]] #Ping down, and (earlier than evening, or later than morning)
then
echo -e "Ping is down, and it is earlier than evening or later than morning"
elif [[ $PINGOUTPUT != 2 && ($currenttime < $evening || $currenttime > $morning) ]] #Ping up,and (earlier than evening, or later than morning)
then
echo -e "Ping is up and it is earlier than evening, or later than morning"
else
echo "WTF?"
fi
done
For arithmetic comparisons you need to use-eq, -lt, etc. From man bash:
arg1 OP arg2
OP is one of -eq, -ne, -lt, -le, -gt, or -ge. These arithmetic
binary operators return true if arg1 is equal to, not equal to,
less than, less than or equal to, greater than, or greater than
or equal to arg2, respectively. Arg1 and arg2 may be positive
or negative integers.
Currently you're doing $currenttime < $evening which is a string comparison.

checking if current time is between two times in HHmmss format in shell script

I have a main script that calls doSomeWork.sh each and every 10 mins.
But the condition is that the doSomeWork.sh should not run between 23:30:00 to 03:00:00.
I have made my script to look something like the below.
#!/bin/ksh
prodStartTime="030000"
prodEndTime="233000"
currentTime=`date +"%H%M%S"`
echo $prodStartTime
echo $prodEndTime
echo $currentTime
while true
do
if [[ $currentTime -ge $prodStartTime && $currentTime -le $prodEndTime ]];
then
./doSomeWork.sh
else
echo Do Nothing
fi
sleep 600
done
UPDATE: Now I have the code working by checking production timings instead of night mode timings(See edit history). But looks like my script is considering the values as Octal as suggested by "twalberg" in the comments. Could someone help me how to take care of these values?
I simply need a way to ensure that my script runs between the specified time span.
Don't compare them numerically (-ge, -le); just compare them as strings. Since ksh doesn't have >= and <=, you can use the equivalent ! < and ! > instead.
if [[ ! "$currentTime" < "$prodStartTime" && ! "$currentTime" > "$prodEndTime" ]]; then
./doSomeWork.sh
fi
But since we're negating, it might be clearer if we apply DeMorgan's Law and only negate once:
if [[ ! ( "$currentTime" < "$prodStartTime" || "$currentTime" > "$prodEndTime" ) ]]; then
./doSomeWork.sh
fi
In any case, when using < and >, there's no interpretation of the strings as numbers (octal or otherwise) to worry about. As long as all the times have the same number of digits, the string comparison will produce the right answer.
I should be calculating the current time inside the loop. But I have calculated only once outside of the loop and using the same value through out the day.
The script should be like.
#!/bin/ksh
prodStartTime="030000"
prodEndTime="233000"
echo $prodStartTime
echo $prodEndTime
echo $currentTime
while true
do
currentTime=`date +"%H%M%S"`
if [[ $currentTime -ge $prodStartTime && $currentTime -le $prodEndTime ]];
then
./doSomeWork.sh
else
echo Do Nothing
fi
sleep 600
done
Somehow this silly mistake was not visible to my eyes.
You could also do it on easy way..
#!/bin/bash
prodStart="132000"
prodEnd="151500"
while [[ ! $(( `date +"%H%M%S"` )) < "$prodStart" && ! $(( `date +"%H%M%S"` )) > "$prodEnd" ]];
do
echo "Do something..."
done
startTime="80000"
endTime="200000"
curTime=$(date +"%H%M%S" | bc)
echo "startTime : "$startTime
echo "endTime : "$endTime
echo "currentTime :"$curTime
echo "curTime < endTime and curTime > startTime then don't execute"
# Messages will be sent only between 8AM to 8PM
if [[ ! ( $curTime -lt "$endTime" && $curTime -gt "$startTime" ) ]];
then
echo "Don't Execute"
else
echo "Execute"
fi

How to use the =~ operand?

I've bumped into a Nagios check script which has been written by someone who already left my company and there's an operator there which I can't understand it's use.
This is the relevant part from the shell script:
if [[ "$URL" =~ $ACTIVE ]] && [[ "$URL2" =~ $ACTIVE2 ]]; then
echo "OK: $HOST is ACTIVE in the Load Balancer"
exit 0
My question is:
What is this =~?
I've checked about it in the internet and found that it's a bitwise which "Flips the bits in the operand", but I don't understand where and how to use it, can you please elaborate?
Edit #1:
This is the full script:
#!/bin/bash
#Purpose: Checks if proxy is active in the LB
#Date: May 09, 2011
#Variables
HOST=$1
URL=`wget --timeout=60 -w 3 -qO- http://$HOST:8080/proxy/keepalive?file=/workspace/temp/1`
URL2=`wget --timeout=60 -w 3 -qO- http://$HOST:8080/proxy/keepalive?file=/workspace/temp/1.txt`
ACTIVE="1"
ACTIVE2="ppp"
LOG="/tmp/PROXY-LB.log"
#Begin Code
if [ -z $HOST ]; then
echo "You must specify IPADDRESS (e.g. 68.67.174.34)"
exit 3
fi
if [[ "$URL" =~ $ACTIVE ]] && [[ "$URL2" =~ $ACTIVE2 ]]; then
echo "OK: $HOST is ACTIVE in the Load Balancer"
exit 0
else
echo "*** Problem: $HOST is out from the Load Balancer"
echo "`date`: *** HOST $HOST is out from the Load Balancer" >> $LOG 2>&1
exit 2
fi
#END
My question is, couldn't the coder use this (without the ~) instead?
if [[ "$URL" = $ACTIVE ]] && [[ "$URL2" = $ACTIVE2 ]]; then
Edit #2:
Here are some examples I tried:
$ d="hello"
$ [[ "$d" =~ *ll* ]] && echo "yes"
$ [[ "$d" =~ he* ]] && echo "yes"
yes
$ [[ "$d" =~ *lo ]] && echo "yes"
$
Edit #3:
Okay, I've done some more tests and I believe I understand it now:
$ [[ "$d" =~ he* ]] && echo "yes"
yes
$ [[ "$d" =~ *lo ]] && echo "yes"
$ [[ "$d" =~ h* ]] && echo "yes"
yes
$ [[ "$d" =~ lo$ ]] && echo "yes"
yes
$ [[ "$d" =~ ^he ]] && echo "yes"
yes
$ [[ "$d" =~ [a-z]ll[a-z] ]] && echo "yes"
yes
$
Thank you all for your help and information!
It is used to perform comparisons in strings.
if [[ "$URL" =~ $ACTIVE ]] && [[ "$URL2" =~ $ACTIVE2 ]]; then
Checks if $URL contains the content of the variable $ACTIVE and if $URL2 contains the content of the variable $ACTIVE2.
See a test:
$ d="hello"
$ [[ "$d" =~ he* ]] && echo "yes"
yes
$ [[ "$d" =~ *ba* ]] && echo "yes"
$
$ [[ $d =~ .*ll.* ]] && echo "yes"
yes
In the last one you have to indicate the regex properly. It is equivalent to using == and just *ll*.
$ [[ $d == *ll* ]] && echo "yes"
yes
From man bash -> 3.2.4.2 Conditional Constructs:
An additional binary operator, =~, is available, with the same
precedence as == and !=. When it is used, the string to the
right of the operator is considered an extended regular expression and
matched accordingly (as in regex(3)). The return value is 0 if the
string matches the pattern, and 1 otherwise. If the regular
expression is syntactically incorrect, the conditional expression's
return value is 2.

Unix scripting whoami/$USER not working as desired

Hi I have the script as below.
if [[ 'whoami' -eq "test" ]]; then
echo "test user"
else
echo "Not a test user"
fi
This is returning test user even if my user is not text. It would be great if someone can pin point my silly mistake.
-eq is for integer testing.
e.g.:
kent$ [[ "a" -eq "b" ]] && echo "y" || echo "n"
y
kent$ [[ 34 -eq 35 ]] && echo "y" || echo "n"
n
try:
kent$ [[ "a" == "b" ]] && echo "y" || echo "n"
n
You are using single quotes in place of backticks:
if [[ `whoami` -eq "test" ]]; then # Not 'whoami'
For improved readability (and easier nesting, if applicable), use
if [[ $(whoami) -eq "test" ]]; then
instead.
Just like this:
if [[ `whoami` == "test" ]]; then # Not 'whoami' -eq
echo "test user"
else
echo "Not a test user"
fi
don't use single quote and '-eq'

Resources