Reputation: 86957
I'm trying to run a shell command (currently either sh
or bash
) which connects to a database. Because the database is still 'warming up', the command fails.
So I was trying to do a loop (let's say ... 100 tries) and each time the command fails, wait 1 second and retry.
If there's an error, this is the start of the string that is dumped to stdout: Sqlcmd: Error: <snipped>
Here's what I've been trying:
for i in $(seq 1 100)
do
X='/opt/mssql-tools/bin/sqlcmd -E -S localhost -Q "<some sql statement> "'
if [[ $X == Sqlcmd: Error:* ]]
echo "."
then
break
fi
done
It's not working as I figure out the string comparison stuff with shell/bash ... but was more making sure if I was on the right track etc.
Upvotes: 1
Views: 857
Reputation: 3097
You could try something like:
while true ; do
if Sqlcmd xxx xxx xxx ; then break ; fi
# or:
Sqlcmd xx xxx xxx && break
sleep 1
done
You can also add a counter:
for ((n=100;n>0;n--)) ; do
Sqlcmd xxx xxx xxx
if [[ $? == 0 ]] ; then
break
fi
sleep 1
done
[[ $n == 0 ]] && echo Timeout && exit 1
I'm showing two different ways of testing the return value here, but the first one is preferred (if cmd ; then ... ; fi
).
$?
is the return value from the last command, which is 0
when it completed successfully. If it returns 0
even in case of error (which can happen for malformed programs), you can test the output with grep
:
Sqlcmd xxx xxx 2>&1 | grep <error pattern> > /dev/null
if [[ $? != 0 ]] ; then break ; fi
Here we test $? != 0
because grep
will return 0
when the error pattern has been found.
If you want to get the output result into a variable, run the command with X=$(Sqlcmd xxx xxx)
. Then you can use bash string comparison:
X=$(Sqlcmd xxx xxx)
if [[ "$X" =~ .*error.* ]] ; then
<handle error here>
fi
Note bash can match regexp, which makes it really handy at checking error types.
You can also use a switch/case
construct:
case "$X" in
*Error:*) echo " Error detected " ;;
*) break ;;
esac
(Note the double ;;
)
Upvotes: 4
Reputation: 86957
I ended up learning all the clues from @matthieu's post. This is what I ended up doing:
for i in $(seq 1 30)
do
/opt/mssql-tools/bin/sqlcmd -U sa -P <snip> -S localhost -Q "USE Master" 2>&1
if [[ $? != 0 ]]
then
# Failed
echo "."
sleep 1s
else
# worked!
break
fi
done
breakdown for those learning (like me)
sqlcmd
command. Any errors via stderr
(that's the 2
in 2>&1
) will be redirected to the console stdout
(that's the $1
). REF: 2>&1 shell idiom. $?
(REF: what is bash dollar questionmark ?)So there we have it! shell/bash shell 101 stuff. good luck!
Upvotes: 1