Running a command until it succeeds
Sometimes a command can only succeed when certain conditions are met. For example, you can only download a file after the file is created. In such cases, one might want to run a command repeatedly until it succeeds.
How to do it...
Define a function in the following way:
repeat() { while true do $@ && return done }
Alternatively, add this to your shell's rc
file for ease of use:
repeat() { while true; do $@ && return; done }
How it works...
This repeat function has an infinite while
loop, which attempts to run the command passed as a parameter (accessed by $@
) to the function. It returns if the command was successful, thereby exiting the loop.
There's more...
We saw a basic way to run commands until they succeed. Let's make things more efficient.
A faster approach
On most modern systems, true is implemented as a binary in /bin
. This means that each time the aforementioned while
loop runs, the shell has to spawn a process. To avoid this, we can use the shell built-in :
command, which always returns an exit code 0:
repeat() { while :; do $@ && return; done }
Though not as readable, this is faster than the first approach.
Adding a delay
Let's say you are using repeat()
to download a file from the Internet which is not available right now, but will be after some time. An example would be as follows:
repeat wget -c http://www.example.com/software-0.1.tar.gz
This script will send too much traffic to the web server at www.example.com
, which causes problems for the server (and maybe for you, if the server blacklists your IP as an attacker). To solve this, we modify the function and add a delay, as follows:
repeat() { while :; do $@ && return; sleep 30; done }
This will cause the command to run every 30 seconds.