A surprising missing Unix command: waiting until a time is reached
A surprising missing Unix command: 'sleep until it is time <X> or later'. Even GNU sleep only sleeps for a duration.
The obvious option here is at
, but at
has a number of drawbacks
that make it far from an ideal experience. For now, I'll just note
that it of course runs your commands non-interactively, and sometimes
you need interactivity. Perhaps you're doing:
waituntil 17:50; rsync -a login@host:/some/thing .
(Which is in fact more or less one of the things that I wanted this for today.)
Original V7 Unix of course had a perfectly sensible reason not to
bother implementing something like this, namely that you can easily
put a reasonable version together by using some shell scripting to
work out how many seconds to tell sleep
to sleep. In the relatively
minimal V7 environment, a dedicated command for waituntil
would
not have been quite out of place and not Unixy. Indeed, I wouldn't
expect traditionally minded Unixes like the *BSDs to pick up such a
program or option to sleep
.
On the other hand, GNU coreutils is a different matter. The GNU
people are perfectly happy to add features to traditional Unix
commands (often quite handy ones), much to the
despair of Unix traditionalists. They have certainly added some
features to GNU sleep
, like multiple arguments in multiple formats,
so it wouldn't have surprised me at all if they'd added a 'sleep
until absolute time <X>' option as well. But they haven't (so far)
and as far as I could tell on a casual perusal of my Linux systems,
no one else has written something like this and gotten it packaged
so it's commonly installed.
Because sometimes I'm a system programmer as well as a sysadmin,
I wound up writing my own version of a waituntil
program. It's in Go because that
seemed the right language and I felt like it.
(I picked Go because the hard part is parsing and manipulating the time argument, and Go actually has a quite nice and flexible system for that. This turned out somewhat more complicated than I expected, but these things happen.)
Sidebar: The right way to do this in the modern Unix API
My version of waituntil
and any version that is based on top of
sleep
have a little problem: they don't necessarily cope with the
system clock changing. If it's 16:10 now, you say 'waituntil
16:20
', and a minute later the system clock jumps to 16:20, you
probably want to have the wait finish right then because you've
reached the target time.
As far as I can see, the correct way to do this on a modern
standards-compliant Unix system is to use clock_nanosleep()
with TIMER_ABSTIME
to wait to an absolute time, and use
CLOCK_REALTIME
as the clock you're doing this against. Given
this, you should be woken the moment the system's clock hits (or
passes) the absolute time you specified, even if the clock is
adjusted forward or backward in the mean time.
(Of course, support for this isn't necessarily there in all Unixes, at least right now.)
Unfortunately for me, Go doesn't expose clock_nanosleep()
(except as a raw Linux syscall, and I don't feel like going there).
For my personal use this is okay, but it would be nice to do better.
Comments on this page:
|
|