Sometimes you just need to try again. And again, and again…
From time to time there will be instances where you need to have a shell command run repeatedly until it succeeds. While most of the time this is indicative of underlying issues, sometimes a fix that is just good enough will be good enough.
Two cases I recently encountered:
- For a tiny legacy project I rarely have to make changes on, the build process would just sometimes fail. Of course, the ‘right’ solution is to fix whatever causes the failures, but time is a finite resource and in this case it really wasn’t worth the effort.
- I needed to push code to a fresh repository, but did not yet have write permissions to it. The admin was unavailable, but I had to leave, so naturally the thing to do was to have the machine git pushup‘ing until permissions were granted and the command succeeds.
In the easiest form, the solution would look like this:
until git pushup do sleep 10 done
git pushup with the command you want to succeed and
sleep 10 with the commands you want run inbetween attempts. I decided to go with
sleep 10 to have a pause of 10 seconds between each request and not run afoul of rate limits. You could simply
echo something to not have a delay.
If you need a shorter notation, for example to be used in an npm command, semicolons can be used:
until git pushup; do sleep 10; done
This is also useful if you have a certain condition you’re waiting for. You could, for example, keep pinging the network address of your roommate’s phone to get notified once he comes home and is in wifi range:
until ping -c 1 -t 5 192.168.178.1 do sleep 1 done echo '\007'
The parameters for the
ping command are important to get this working right.
-c 1 will have the command only try a single ping instead of an unlimited amount of time, and
-t 5 sets the timeout to 5 seconds.
echo command prints an
ASCII BEL, which will cause your terminal to emit an alert sound. Of course, you could use any other command here, for example to send you an email, use the OS notification system, or whatever else you can come up with!
If, on the other hand, you maybe are more concerned with avoiding other people and want to be notified once your roommate leaves so you can get a glass of water without running into anyone, the logic can easily be reversed:
while ping -c 1 -t 5 192.168.178.1 do sleep 1 done echo '\007'
This will beep once the
ping command fails.