A simple way to synchronize the computers on your network

Many networks run every day with administrators unconcerned about time synchronization on the individual computers in the network. However, some applications require that the computers be synchronized. In software development, for example, the make command uses the time and date stamp on the source code files to decide which files need to be compiled and which may be skipped. If your computers lose synchronization, some files may not be compiled when needed, and others may compile repeatedly because the time stamp shows that the source file is still newer than the object file.

 In our shop, we had exactly this problem. Changes we knew had been made wouldn't make it into the latest test release. Similarly, some compile cycles would take far too long. We finally tracked this problem down to its source: the drifting clocks between computers.
 
 

Centralized time management

Once we tracked down the problem, we set the date on all the computers and went off to develop software. A couple of months later, the problems began again. This time, we decided to completely eliminate the problem. Our first attempt was to create a cron job on the time server that uses the remote shell (rsh) command to execute the date command on each computer we wanted to synchronize, like this:
rsh Zeus date 1005
However, this technique has a couple of minor problems. First, we may not have an account on each of those computers, so we must specify the account on which we want to log in. Second, only the root account may change the time on the computer, and we want to keep the root account secure with a password. Since we have a password on the root account, we can't just tell rsh to execute the date command as root on the remote computer, using the command:
rsh Zeus -l root date $TIME
To solve the first problem, we created a specific user account, named time, to run the date command. We then made the date command always run as if it were the root user. To do so, we turned on the suid permission bit--as well as the execute permissions for the date command--on each computer, like this:
# chmod 4711 /usr/bin/date
Making these concessions gives us the TimeSync script, as shown in Listing A.

 Listing A: TimeSync

#! /bin/ksh

# Get the current time on this machine, the
# `Time Server'.
TIME='date `+%m%d%H%M''

# Set the time on all the client machines
# using the time account.
rsh Zeus -l time date $TIME
rsh Hydra -l time date $TIME
rsh Cerebus -l time date $TIME
rsh Loki -l time date $TIME
rsh Thor -l time date $TIME
Now we have a centrally managed method to synchronize time on the network. However, a user can still set the time and date on an individual computer, potentially wreaking havoc. Also, since we made the date command run as root, we opened a possible security loophole.

We could easily fix these problems by making a new copy of the date command and placing it in a secure area that only the time account could access. Instead, we decided to make each user responsible for synchronizing his or her own computer to the time server if they so desired.

Distributed synchronization

Placing the responsibility for computer synchronization on the user turned out to be a better solution for us. This way, we could publish a method that anyone wanting synchronization could use, and we relied on the software developers to administer themselves in this regard. The method we used to do this was very similar to the one we just described. But rather than making the server use rsh to execute the date command on all the clients, we make each client ask the date from the server, like this:
rsh Mercury date
Again, we don't want to put every possible user account on our time server, so we created the time account on it. Now, everyone can use the same account to find the current "correct" time:
rsh Mercury -l time date
At this point, we only need to make the local computer set the time to the value just stated by Mercury, our time server--a simple enough process. If we pass the proper format string to the date command on Mercury, then we can pass the results directly into the date command on the client machine.

We opted to use the full precision offered by Solaris. Thus, when we install a computer on the network, we needn't worry about setting the date or time at all. It may be set automatically to the correct date, from the century to the second. Our statement that gets the current time from Mercury looks like this:

rsh Mercury -l time /usr/xpg4/bin/date +'%m%d%H%M%C%y.%S'
Please note that we're using the XPG4 version of the date command to get the century (%C) from date. If you didn't install the SUNWxcu4 package, you don't have this version of the date command. In that case, go ahead and use the standard date command, and use 19 instead of %C in the format string. (Don't forget to change it in two years!)

 First, we create a script file, named Sync, that reads the time from the time server and sets the local time, as shown in Listing B.

 Listing B: Sync script

#! /bin/ksh

# Ensure that we're using the XPG4 version of date
# (it supports the %C format specifier).
DATE=/usr/xpg4/bin/date

# Specify the host and account that will provide
# the `correct' date and time.
TSRV="Mercury -lTime"
We're almost finished. All that's left is to periodically run the Sync script to synchronize the computer to our reference computer. Again, only the root account may set the date and time on a machine. In this case, however, there's no problem. Since the root account already runs several cron jobs, we're just going to add another one to periodically set the date and time. So we'll just add a crontab entry that runs our Sync script every hour, as in the following line, and never again be bothered about the time:
0 * * * * /usr/local/Sync

NTP

These two methods of synchronizing the time on your computers are certainly very simple. However, the synchronization achievable with these techniques are only accurate to within a second or two of your time server. And just how well does your time server keep track of time? Solaris 2.6 brings plenty of new features to the table. One of these is the NTP protocol for time synchronization of multiple computers on a network. Using NTP, you can synchronize your computers to amazingly tight tolerances, since this protocol even performs some adjustments for network delays on your network. (Please note: You can also get NTP in source code form, so you can install it on any version of Solaris.)

 One of my team downloaded a copy of xntp, which is a freely available program that implements the NTP protocol for synchronizing time on a network of computers. It's a very powerful tool, but much more than we really needed, especially when some of the network computers were relatively underpowered and had no RAM to spare for yet another application.

 Consequently, we decided to run xntp on only one computer, having it keep track of the correct time on one of the available time servers on the Internet. Then we used this as our time server and used our simple synchronization scheme for the other computers on our network.

Summary

Many networks don't really need to worry about time synchronization. For many of those that do, tight precision isn't a necessity--a few seconds either way isn't significant. For these applications, one of our synchronization schemes is simple to implement and use. However, those applications that require more precise synchronization should consider NTP, even though it brings more complexity and overhead with its improved precision.

<< Back to Tech Corner