Repeatedly run a shell command until it fails?
BashBash Problem Overview
I've written a fuzzy test that fails unreliably. I've added some debug code, but now I want to run the test until it fails so I can gather the debug output.
I've setup the test so I can run it using:
./runtest
My current solution is to write an untilfail
script:
#!/bin/bash
$@
while [ $? -eq 0 ]; do
$@
done
Then use it:
untilfail ./runtest
Is there a simpler solution?
Bash Solutions
Solution 1 - Bash
while
takes a command to execute, so you can use the simpler
while ./runtest; do :; done
This will stop the loop when ./runtest
returns a nonzero exit code (which is usually indicative of failure).
To further simplify your current solution though, you should just change your untilfail script to look like this:
#!/bin/bash
while "$@"; do :; done
And then you can call it with whatever command you're already using:
untilfail ./runTest --and val1,val2 -o option1 "argument two"
Solution 2 - Bash
If you don't want to wrap a complex pipe line into a shell script or function then this works:
while true; do
curl -s "https:..." | grep "HasErrors.:true"
if [[ "$?" -ne 0 ]]; then
break
fi
sleep 120
done
The HTTP request in this case always returns 200 but also returns some JSON which has an attribute "HasErrors":true when there is an error.
Solution 3 - Bash
Having had a similar problem in a system that had shell retry logic duplicated everywhere I made a dedicated tool to solve this called "retry":
retry --until=fail ./runtest
A more complex example:
retry --until=fail --message="test succeeded" --delay=1 ./runtest
Tool available from https://github.com/minfrin/retry.
Solution 4 - Bash
On Ubuntu:
sudo apt-get install run-one
run-one-until-failure COMMAND [ARGS]
For more information: https://blog.dustinkirkland.com/2013/09/introducing-run-one-constantly-run-one.html
Solution 5 - Bash
One can also use the watch
command with the -e
flag which runs the command until an error occurs (and then freezes the output until a key is pressed):
watch -e ./runtest
The only downside of using watch is that there's a mandatory delay of at least 0.1s between runs:
watch -e ./runtest -n0.1
Witch watch
you can also highlight output changes between runs (-d
) or exit when the output of the command changes (-g
).