I have a script that looks like this, this script is checking whether my pods is in Running state or Not by redefining x on every loop.
x=$(/opt/oc get pods --selector app=${bamboo.shortPlanName} -o jsonpath='{range .items[]}{.status.phase}{"\n"}{end}')
until [ "$x" == "Running" ];
do
sleep 5
x=$(/opt/oc get pods --selector app=${bamboo.shortPlanName} -o jsonpath='{range .items[]}{.status.phase}{"\n"}{end}')
echo $x
done
But, I want to modify my current script to also support timeout, I mean after 60 second of looping, then it should be stop, or after 12 times of looping, then it should be stop. Any idea how to do that?
CodePudding user response:
bash
provides a special variable SECONDS
that can be used as a rough timer.
SECONDS=0
while (( SECONDS < 60)); do
x=$(/opt/oc get pods --selector app=${bamboo.shortPlanName} -o jsonpath='{range .items[]}{.status.phase}{"\n"}{end}')
if [[ $x == Running ]]; then
break
fi
sleep 5
done
The expansion of SECONDS
gives you not the assigned value, but the difference between the numbers of seconds since the assignment and the assigned value. The effect is like a variable whose value is incremented by 1 each second.
CodePudding user response:
I think trap
is the easiest way to have an accurate timeout.
Prototype:
#! /bin/bash
HALT=0
TIMEOUT=4
# Trap for SIGALRM
stop_loop() {
HALT=1
}
# Set trap
trap stop_loop SIGALRM
# The timeout goes after $TIMEOUT seconds.
{ sleep $TIMEOUT && kill -SIGALRM $$ & }
# Main loop
until false || [[ $HALT -eq 1 ]]; do
sleep 1
echo 'loop'
done
echo 'out of loop'
exit 0
In your case, this looks a something like:
HALT=0
TIMEOUT=4
stop_loop() {
HALT=1
}
trap stop_loop SIGALRM
x=$(/opt/oc get pods --selector app=${bamboo.shortPlanName} \
-o jsonpath='{range .items[]}{.status.phase}{"\n"}{end}')
{ sleep $TIMEOUT && kill -SIGALRM $$ & }
until [ "$x" == "Running" ] || [[ $HALT -eq 1 ]];
do
sleep 5
x=$(/opt/oc get pods --selector app=${bamboo.shortPlanName} \
-o jsonpath='{range .items[]}{.status.phase}{"\n"}{end}')
echo $x
done
exit 0
CodePudding user response:
For timeout after 60 seconds try this Shellcheck-clean code:
#! /bin/bash -p
readonly kOC_SLEEP_SECS=5
readonly kOC_TIMEOUT_SECS=60
initial_secs=$SECONDS
while
status=$(/opt/oc get pods --selector app=bamboo.shortPlanName \
-o jsonpath='{range .items[]}{.status.phase}{"\n"}{end}')
printf '%s\n' "$status"
[[ $status != Running ]]
do
if (( (SECONDS - initial_secs) >= kOC_TIMEOUT_SECS )); then
echo 'ERROR: Timed out' >&2
exit 1
fi
sleep -- "$kOC_SLEEP_SECS"
done
- I replaced
app=${bamboo.shortPlanName}
withapp=bamboo.shortPlanName
because the old code was causing Bash errors. You'll need to fix it properly. - See Why is printf better than echo? for an explanation of why I replaced
echo
withprintf
for printing the status. - The code treats a timeout as an error, and exits with bad status. You might want to do something different.
- The actual timeout period will be somewhere between 60 and 65 (or maybe a little more) seconds. You'll need to do something different if you need a more accurate timeout.
For a timeout after 12 iterations try this Shellcheck-clean variation on the code above:
#! /bin/bash -p
readonly kOC_SLEEP_SECS=5
readonly kOC_MAX_ITERS=12
oc_iters=0
while
status=$(/opt/oc get pods --selector app=bamboo.shortPlanName \
-o jsonpath='{range .items[]}{.status.phase}{"\n"}{end}')
printf '%s\n' "$status"
[[ $status != Running ]]
do
if (( oc_iters >= kOC_MAX_ITERS )); then
echo 'ERROR: Timed out' >&2
exit 1
fi
sleep -- "$kOC_SLEEP_SECS"
done