We began on the djb way with the clockspeed package. That got us started with downloading, building, installing and running a representative piece of djb software. Coincidentally, perhaps, our clocks may even be running a little more accurately now.
But the original operating instructions left a lot to be desired. Sure, we may have started the clockspeed background daemon at one time, but we didn't make any special arrangments to be sure it started again with each system reboot. And the periodic calibration procedure required us to remember to do something from the command line every so often, after a few hours, then days, then weeks, then months apart. Hah! Not likely!
Now that we have the
daemontools
utilities at our disposal, though,
we can make better use of the clockspeed package as a serious network time server.
This section will describe
clockspeed service daemons
as an example
of running clockspeed under daemontools the djb way.
Recall that the clockspeed package includes the following components:
clockspeed: a utility for constantly adjusting the system clock (every 3 seconds), designed to run continuously as a background process.
sntpclock: a utility for periodically taking a precise timing mark from an NTP time server, used for both setting the system clock (with clockadd), and for calibrating a running clockspeed process.
taiclock: a utility similar to sntpclock, only taking its timing mark from a server following Bernstein's TAICLOCK protocol.
taiclockd: a utility for providing a TAICLOCK protocol service, designed to run continuously as a background process, listening and responding to UDP connections on port 4014.
Our goal is to use daemontools for creating a set of clockspeed services that:
In addition,
it would be nice to log the activities of these services,
so we can monitor what clockspeed is doing behind the scenes
.
The clockspeed services of course require the clockspeed package. The scripts described here also make use of our clockctl interface to the clockspeed functions.
The clockspeed services will then consist of a set of
daemontools run
scripts and supporting utilities that will be
defined within the /var/svc.d directory.
To prepare the framework, make these directories now:
# mkdir -p /var/svc.d # cd /var/svc.d # mkdir -p clockspeed/log # mkdir -p clockspeed_adjust/log # mkdir -p taiclockd/log
We will also be introducing the
setuidgid utility of daemontools,
to run our services at reduced privelege levels whenever possible.
To prepare for this, add the group nofiles
,
and two users named
clocksd
and multilog
--both members
of group nofiles
--to your system,
in accordance with the conventions for your particular platform.
The clocksd
user will be used to run some of the clockspeed service daemons,
while the multilog
user will be used to run the logging services.
As a security measure,
these users will have non-root priveleges.
The group nofiles
will be a constant companion along the djb way.
Most of the unpriveleged users we meet will be members of this group.
The daemontools run
script for clockspeed is simple:
#!/bin/sh # clockspeed/run # "run" script for a clockspeed daemon exec 2>&1 echo "*** Starting clockspeed..." exec /usr/local/clockspeed/bin/clockspeed # that's all, folks!
Save this to /var/svc.d/clockspeed/run and make it executable, chmod 755.
Note that in this run
script,
the clockspeed executable is run in the foreground.
That is, no ampersand (&) follows the command
as when we ran it from the command line.
This is a crucial aspect of services run under daemontools:
they must run in the foreground.
The daemontools supervise process will take care of
running the command as a background daemon for us.
Next is a logger for the clockspeed service. Although the clockspeed utility itself doesn't generate any output, the echo line in the run script above will make multilog generate a timestamp for logging the start-up.
#!/bin/sh # clockspeed/log/run # "run" script for clockspeed multilog exec setuidgid multilog multilog t /var/multilog/clockspeed # that's all, folks!
Save to /var/svc.d/clockspeed/log/run, make it executable, chmod 755.
The new daemontools twist to notice here is the
setuidgid utility as the command that is exec'd.
This has the effect of running
multilog as an unpriveleged user;
here we specify the username multilog
,
the user we created specifically for logging when we set up the framework earlier.
There's one more step now for the logging service. Since multilog will be run as an unprivleged user, the log directory needs to be owned by that user:
# mkdir -p /var/multilog/clockspeed # chown multilog:nofiles /var/multilog/clockspeed
This pair of scripts will now run clockspeed under control of daemontools with logging. Activate the service by linking it into the /service directory:
# ln -s /var/svc.d/clockspeed /service/clockspeed
After the service starts, set ownership on the special named pipe created by clockspeed:
# chown clocksd /usr/local/clockspeed/adjust
The clockspeed_adjust
service set up below will then be
able to run as this non-priveleged user.
Now we want a background service that periodically remembers to get a new timing mark from an external timeserver. The main job is done by a simple script:
#!/bin/sh # clock_adjust.sh # periodically get timing mark for clockspeed service # # initialize WAIT, WAIT_MAX: WAIT=541 WAIT_MAX=2617923 # loop indefinitely while : do echo "Waiting ${WAIT} seconds until next adjustment..." sleep ${WAIT} # obtain timing mark for calibrating clockspeed adjust: clockctl mark # log current "attoseconds": clockctl atto echo "===" # increment $WAIT: WAIT=`expr ${WAIT} + ${WAIT} + ${WAIT}` if [ ${WAIT} -gt ${WAIT_MAX} ] ; then WAIT=${WAIT_MAX} fi done # that's all, folks!
Save this script to /var/svc.d/clockspeed_adjust/clock_adjust.sh, chmod 755.
(Note: OpenBSD users may have problems with the use of sleep in this shell script. Please refer to the notes regarding the OpenBSD /bin/sh shell anomaly, and possible work-arounds.)
This script is designed for a continuously running, network connected host. It uses a single loop to periodically get a new timing mark from an external timeserver, with an ever-lengthening interval between each loop, up to a maximum interval defined by $WAIT_MAX.
Notice that this script calls the clockctl interface we previously installed for operating clockspeed.
The daemontools run
script for the
clockspeed_adjust
service then looks like this:
#!/bin/sh # clockspeed_adjust/run # "run" script for a clockspeed_adjust daemon exec 2>&1 echo "*** Starting clockspeed_adjust..." exec setuidgid clocksd ./clock_adjust.sh # that's all, folks!
Save this script to /var/svc.d/clockspeed_adjust/run, chmod 755.
Here again we use the daemontools
setuidgid utility.
Only in this case,
the
clock_adjust.sh script is now set up to run
with reduced priveleges as user clocksd
.
The logging service for clockspeed_adjust should be getting familiar by now:
#!/bin/sh # clockspeed_adjust/log/run # "run" script for clockspeed_adjust logger exec setuidgid multilog multilog t /var/multilog/clockspeed_adjust # that's all, folks!
Save this script to /var/svc.d/clockspeed_adjust/log/run, chmod 755. (Hello? Is there an echo in here?)
Again we use
setuidgid on the logging service,
to run the service as the unpriveleged multilog
user.
Configure the log directory for the service:
# mkdir -p /var/multilog/clockspeed_adjust # chown multilog:nofiles /var/multilog/clockspeed_adjust
This set of scripts will now run a clockspeed_adjust service under control of daemontools with logging.
Activate the service by linking it into the /service directory:
# ln -s /var/svc.d/clockspeed_adjust /service/clockspeed_adjust
Optionally you may want to set up a host on a network to serve time, using Bernstein's taiclockd server. This server should itself be calibrated to an external time server as described above.
Setting up a taiclockd service then involves a familiar pair of
simple daemontools run
scripts.
The main run
script for the service looks like this:
#!/bin/sh # taiclockd/run # "run" script for a taiclockd daemon exec 2>&1 echo "*** Starting taiclockd..." exec setuidgid clocksd /usr/local/clockspeed/bin/taiclockd # that's all, folks!
As usual, install the script in /var/svc.d/taiclockd/run, chmod 755.
Notice again that taiclockd is run with the reduced
priveleges of user clocksd
.
Here now is the logging service:
#!/bin/sh # taiclockd/log/run # "run" script for taiclockd multilog exec setuidgid multilog multilog t /var/multilog/taiclockd # that's all, folks!
Familiar stuff, right? Install in /var/svc.d/taiclockd/log/run, chmod 755.
Set up the directory for multilog:
# mkdir -p /var/multilog/taiclockd # chown multilog:nofiles /var/multilog/taiclockd
Everything should be good to go. Activate the service by linking into /service:
# ln -s /var/svc.d/taiclockd /service/taiclockd
Clients of this time server should be set up according to the
operating instructions of clockspeed,
along with clockspeed
and clockspeed_adjust
services as described above.
Just edit the clients' clockspeed.conf file in /usr/local/etc,
setting CLOCK_TYPE="tai",
and CLOCK_IP to the IP address of this local time server.
Copyright © 2002, 2003, 2004, Wayne Marshall.
All rights reserved.
Last edit 2004.10.04, wcm.