How can this while loop be limited to maximum 10 retries?
#!/bin/sh
while ! test -d /somemount/share/folder
do
echo "Waiting for mount /somemount/share/folder..."
sleep 1
done
Keep a counter:
#!/bin/sh
while ! test -d /somemount/share/folder
do
echo "Waiting for mount /somemount/share/folder..."
((c++)) && ((c==10)) && break
sleep 1
done
You can also use a for loop and exit it on success:
for try in {1..10} ; do
[[ -d /somemount/share/folder ]] && break
done
The problem (which exists in the other solutions, too) is that once the loop ends, you don't know how it ended - was the directory found, or was the counter exhausted?
I would comment but I do not have enough points for that. I want to contribute anyway.
So this makes it work even if the while loop is nested in another loop. before the break the c variable is being reset to zero.
credits to #anubhava who came up with the original solution.
#!/bin/sh
while ! test -d /somemount/share/folder
do
echo "Waiting for mount /somemount/share/folder..."
((c++)) && ((c==10)) && c=0 && break
sleep 1
done
You can use until (instead of "while ! ... break), with a counter limit:
COUNT=0
ATTEMPTS=10
until [[ -d /somemount/share/folder ]] || [[ $COUNT -eq $ATTEMPTS ]]; do
echo -e "$(( COUNT++ ))... \c"
sleep 1
done
[[ $COUNT -eq $ATTEMPTS ]] && echo "Could not access mount" && (exit 1)
Notes:
Just like setting counter as variable, you can set var condition="[[ .. ]]", and use until eval $condition to make it more generic.
echo $(( COUNT++ )) increases the counter while printing.
If running inside a function, use "return 1" instead of "exit 1".
Related
I want to apply dark theme depending on if it is "AM" or "PM". So I have created a bash script with "while loop" (So that it runs forever).
But running this script causes speed up in cpu fan. (that happens when our pc struggles to do something highly computational or playing game or anything heavy).
My script is just a simple line. So how can I run this script without causing high fan speeding?
#!/bin/bash
isNightThemeApplied=0
isDayThemeApplied=0
while [[ 1 -le 1 ]]
do
if [[ `date +%r` == *"AM"* ]]
then
if [[ isNightThemeApplied -eq 0 ]]
then
echo "Applying Night Theme..."
lookandfeeltool -a 'org.kde.breezedark.desktop'
isNightThemeApplied=1
isDayThemeApplied=0
echo "Night Theme Applied Successfully"
fi
else
if [[ isDayThemeApplied -eq 0 ]]
then
echo "Applying Day Theme..."
lookandfeeltool -a 'org.kde.breeze.desktop'
isDayThemeApplied=1
isNightThemeApplied=0
echo "Day Theme Applied Successfully"
fi
fi
done
You could do something like this that uses a while loop every 30 minutes so hardly resource hungry, no need to echo anything in my opinion, just put this in your start up script and run it.
#!/usr/bin/env bash
a=$(date +%p)
b="PM"
c="AM"
theme_change () {
if [[ "$a" == "$b" ]] ; then
lookandfeeltool -a 'org.kde.breezedark.desktop'
elif [[ "$a" == "$c" ]] ; then
lookandfeeltool -a 'org.kde.breeze.desktop'
fi
}
while true; do
theme_change;
sleep 1800;
done
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
For example, in the below script startover starts back from the top:
##########################################################################
## CHECK TIME
##########################################################################
time=$(date +%k%M)
if [[ "$time" -ge 1800 ]] && [[ "$time" -le 2200 ]];then
echo "Not a good time to transcode video!" && exit 0
else
echo "Excellent time to transcode video!" && echo "Lets get started!"
fi
##########################################################################
## CHECK TIME
##########################################################################
startover
Also keeping in mind exit 0 should be able to stop the script.
You could "recurse" using the following line:
exec bash "$0" "$#"
Since $0 is the path to the current script, this line starts the script without creating a new process, meaning you don't need to worry about too many restarts overflowing the process table on your machine.
Put it in a while loop. I'd also suggest you add a "sleep" so that you're not racing your machine's CPU as fast as it will go:
while true; do
##########################################################################
## CHECK TIME
##########################################################################
time=$(date +%k%M)
if [[ "$time" -ge 1800 ]] && [[ "$time" -le 2200 ]]; then
echo "Not a good time to transcode video!" && exit 0
else
echo "Excellent time to transcode video!" && echo "Lets get started!"
fi
##########################################################################
## CHECK TIME
##########################################################################
for i in {1..5}; do
echo $i
sleep 1
done
done
DO NOT USE WHILE LOOP at the start of the script since the condition below will exit the script and break the loop.
echo "Not a good time to transcode video!" && exit 0
You can try trapping the exit signal so that when the script exits it restarts
##########################################################################
## CHECK TIME
############bash##############################################################
trap '<path to script> ' EXIT
time=$(date +%k%M)
if [[ "$time" -ge 1800 ]] && [[ "$time" -le 2200 ]];then
echo "Not a good time to transcode video!" && exit 0
sleep 1;
else
echo "Excellent time to transcode video!" && echo "Lets get started!"
sleep 1;
fi
##########################################################################
## CHECK TIME
##########################################################################
echo 1
echo 2
echo 3
echo 4
echo 5
startover
Note: I add a sleep of 1 second because this will give you the time to see message. trap the exit signal and re-running the script is acting like a while loop. I am also assuming that these codes are in a script.
How about enclosing the entire script in a while loop? For example,
while :
do
script
done
You may want to add a condition to break out of the loop.
This is not good practice, but what you asked for.
Put this at the end of your script. "$( cd "$( dirname "$0" )" && pwd )/$(basename $0)"
How can this while loop be limited to maximum 10 retries?
#!/bin/sh
while ! test -d /somemount/share/folder
do
echo "Waiting for mount /somemount/share/folder..."
sleep 1
done
Keep a counter:
#!/bin/sh
while ! test -d /somemount/share/folder
do
echo "Waiting for mount /somemount/share/folder..."
((c++)) && ((c==10)) && break
sleep 1
done
You can also use a for loop and exit it on success:
for try in {1..10} ; do
[[ -d /somemount/share/folder ]] && break
done
The problem (which exists in the other solutions, too) is that once the loop ends, you don't know how it ended - was the directory found, or was the counter exhausted?
I would comment but I do not have enough points for that. I want to contribute anyway.
So this makes it work even if the while loop is nested in another loop. before the break the c variable is being reset to zero.
credits to #anubhava who came up with the original solution.
#!/bin/sh
while ! test -d /somemount/share/folder
do
echo "Waiting for mount /somemount/share/folder..."
((c++)) && ((c==10)) && c=0 && break
sleep 1
done
You can use until (instead of "while ! ... break), with a counter limit:
COUNT=0
ATTEMPTS=10
until [[ -d /somemount/share/folder ]] || [[ $COUNT -eq $ATTEMPTS ]]; do
echo -e "$(( COUNT++ ))... \c"
sleep 1
done
[[ $COUNT -eq $ATTEMPTS ]] && echo "Could not access mount" && (exit 1)
Notes:
Just like setting counter as variable, you can set var condition="[[ .. ]]", and use until eval $condition to make it more generic.
echo $(( COUNT++ )) increases the counter while printing.
If running inside a function, use "return 1" instead of "exit 1".
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