Hasan Can Saral Hasan Can Saral - 5 months ago 8
Bash Question

How Can I Run A Command That Does Not Exit Upon Failure Until It Succeeds?

I have a

Docker
container running
HBase
See here for more details about it. Basically, it takes around 30s for HBase to come alive.

Obviously I have other containers depending on this one. In one of them, in
docker-entrypoint.sh
I am basically doing this:

#!/bin/bash

/path/to/command argument

while [ $? -ne 0 ]; do
sleep 2;
/path/to/command argument
done


The problem here is that the
/path/to/command
is something that deploys a webserver, that would interact with
HBase
container. If it succeeds, it is blocking the current process (which is fine, since it is in a container), but in a same way, if it fails, it prints the stack trace but does not exit with some
-ne 0
code (Actually, does not exit at all). In fact, if it exits
--restart=always
would handle it.

So, my question here is that how can I keep it retrying until it succeeds, basically without exiting with some fail code? Exiting from the
Docker
container is also an option, so that it can keep restarting until success. For now, I do not have the opportunity to modify the not exiting code to exit.

Update:



I had to do like this:

#!/bin/bash

tmp=$(mktemp)
/path/to/command args 2> "$tmp" &

while true; do
sleep 5;
if [ -s "$tmp" ]; then
exit
fi
done


Basically, I had to run it in the background so that the script above would continue executing (
path/to/command
is a UI blocking command -such as
listen
of a server - that does not exit when succeeds -it listens- nor when it fails -it should have, this is why I am asking this question-).

So in order for Docker container not to exit , I had to add a
while true;
loop, in which I am checking if there is an error in
$tmp
. If there is, I simply
exit
.

Update 2:



I changed the bash script to:

#!/bin/bash

/path/to/command args &

while true; do
sleep 10;

response=$(curl --write-out %{http_code} --silent --output /dev/null http://localhost);

if [ "$response" != "200" ]; then
exit
fi

done


since my container is deploying a web server, I am at least monitoring its status in the main thread, after starting it. Still there's room for improvement.

Answer

You could try redirecting stderr to a file, and then check if said file is empty:

tmp=$(mktemp)
/path/to/command argument 2> "$tmp"

# Run code until "$tmp" is empty
until [ -s "$tmp" ]; do
  sleep 2
  /path/to/command argument 2> "$tmp"
done

rm "$tmp"
Comments