Jérôme Belleman
Home  •  Tools  •  Posts  •  Talks  •  Travels  •  Graphics  •  About Me

Trying a Command Until It Works

6 May 2017

Some commands only need time before they eventually succeed. As part of your workflows, it can be useful to know when that happens, e.g. to trigger actions.

1 It's All About Multitasking

It's all about multitasking again, and not having to idly wait for something to happen. When you think about it, it's something that happens all the time, with computing. And yet it took me too long to realise there was something to do about it.

It was on a bright summer day when I'd spawned a couple of virtual machines and was eagerly waiting for them to be ready to SSH into that it occurred to me that I was wasting my time and well better off doing something else until they were ready. Googling for ideas, I soon realised that the solution was so obvious I felt embarrassed. Any modern shell comes with loop structures and the until loop makes it easy to express this very naturally:

until ssh root@mynewvm; do sleep 10; done

This can naturally be improved by adding notification to it and even taking advantage of urgency hints:

until ssh root@mynewvm; do sleep 10; done; echo -e \\a

2 What If It Never Succeeds?

You wouldn't want your until loop to run forever in such a case. The timeout command can be of some use, here. But getting it to work might turn out to be tricky. For instance, setting up a timeout of 12 hours by running:

timeout 12h until ssh root@mynewvm; do sleep 10; done # This won't work

... or even:

timeout 12h 'until ssh root@mynewvm; do sleep 10; done' # This won't work either

... will not work because timeout expects as the COMMAND argument an executable file and until is neither a file, let alone a command. And the whole until loop in quotes even less so. However, using bash or any other shell to pass it a command works as expected:

timeout 12h bash -c 'until ssh root@mynewvm; do sleep 10; done'

Again, you can add to this some notification. Appending it to the quoted command line you pass bash will work, but it's probably best to run it even after timeout so that you're notified no matter what, whether your command eventually succeeds or times out:

timeout 12h bash -c 'until ssh root@mynewvm; do sleep 10; done'; echo -e \\a

3 Other Approaches

Looking for an online manual page of timeout, I stumbled upon hatimerun which appears to serve similar purposes. I couldn't find this tool provided in any of the packages available for Ubuntu and didn't look any further. But it could be worth looking into nonetheless.

4 References