|
NTP Time Synchronization Script
Written by Tony Bhimani
April 10, 2006
Requirements
*nix based Operating System
PHP 3, 4, 5
Download the source code: ntpscripts.tar.gz
The NTP Time Synchronization script is an alternative to using ntpdate.
The script is run from cron on a daily basis or can be executed more frequently.
An array of time servers is created to query the current date/time and
achieves failover by polling one server at a time for the server count.
If by some chance all servers either refuse the connection or send back
an invalid response, the script will be run the next day. Once a valid
response is received it is parsed to a numeric value and the current date
and time is calculated from that. The system time is set using the date
program by passing the new date/time. There is an optional line that also
updates the hardware clock so both time sources are in sync. Included
in the archive is two additional scripts that can be used to keep either
the system time or hardware clock in sync on a regular interval. I came
across a problem on one system I built that the system time kept losing
ticks. I never could find a solution and opted for a band-aid fix. If
you receive a message like Losing too many ticks! TSC cannot be
used as a timesource. (Are you running with SpeedStep?) Falling back to
a sane timesource then the included clocktosys.php file should
be added to cron and be run every 5 minutes. I've been using it for the
last 3 months and it hasn't failed - both times stay in sync. If you experience
the opposite (system time is right but your hardware clock is wrong) then
use systoclock.php.
Installation
Extract the archive to a directory like /root/scripts or somewhere else
of your choice. Edit ntpsynctime.php and change the $time_adjustment variable
for your region. The script will work for the PST time zone where I am
but other regions will have an offset. For example, if you're in EST or
3 hours ahead of PST then the adjustment should be set to the number of
seconds difference being 10800 (60 seconds * 60 minutes * 3 hours). If
you're behind PST time then use negative seconds. It's pretty self explanitory.
Also change the paths to the date and clock programs for your operating
system. Use the which command to get the path to each application.
If you run this on Linux then the defaults should work. Also be sure to
chmod 755 the scripts so they're executable.
Setting up the Cron job
Assuming you installed the scripts to /root/scripts then you can add
a cron job for ntptimesync.php to /etc/crontab like so.
00 0 * * * root /root/scripts/ntptimesync.php > /dev/null 2>&1
The script will run every night at midnight and won't send the output
as emails to root (if you want to receive the emails then remove the
> /dev/null 2>&1).
If your system time is losing ticks then add clocktosys.php to crontab
and have it run every 5 minutes to update from your hardware clock.
*/5 * * * * root /root/scripts/clocktosys.php
or if your hardware clock is running out of sync then update it with
the system time.
*/5 * * * * root /root/scripts/systoclock.php
Summary
All the scripts are very basic. I tried to include a lot of comments
to explain what happens at each section of code. One thing these scripts
teach is that you can run PHP scripts as shell scripts. At the top of
each file is the shebang. The -q flag supresses HTTP header output. If
you're more comfortable with PHP as opposed to bash or Perl then you can
use it for writing some handy scripts to automate processes like exporting
databases, rotating your Apache logs, and other things. I will be posting
scripts like those at a later date.
Source Code:
#!/usr/bin/php -q
<?php
// ntp time servers to contact
// we try them one at a time if the previous failed (failover)
// if all fail then wait till tomorrow
$time_servers = array("time.nist.gov",
"nist1.datum.com",
"time-a.timefreq.bldrdoc.gov",
"utcnist.colorado.edu");
// date and clock programs (change for your system)
$date_app = "/bin/date";
$clock_app = "/sbin/clock";
// a flag and number of servers
$valid_response = false;
$ts_count = sizeof($time_servers);
// time adjustment
// I'm in California and the clock will be set to -0800 UTC [8 hours] for PST
// you will need to change this value for your region (seconds)
$time_adjustment = 0;
for ($i=0; $i<$ts_count; $i++) {
$time_server = $time_servers[$i];
$fp = fsockopen($time_server, 37, $errno, $errstr, 30);
if (!$fp) {
echo "$time_server: $errstr ($errno)\n";
echo "Trying next available server...\n\n";
} else {
$data = NULL;
while (!feof($fp)) {
$data .= fgets($fp, 128);
}
fclose($fp);
// we have a response...is it valid? (4 char string -> 32 bits)
if (strlen($data) != 4) {
echo "NTP Server {$time_server} returned an invalid response.\n";
if ($i != ($ts_count - 1)) {
echo "Trying next available server...\n\n";
} else {
echo "Time server list exhausted\n";
}
} else {
$valid_response = true;
break;
}
}
}
if ($valid_response) {
// time server response is a string - convert to numeric
$NTPtime = ord($data{0})*pow(256, 3) + ord($data{1})*pow(256, 2) + ord($data{2})*256 + ord($data{3});
// convert the seconds to the present date & time
// 2840140800 = Thu, 1 Jan 2060 00:00:00 UTC
// 631152000 = Mon, 1 Jan 1990 00:00:00 UTC
$TimeFrom1990 = $NTPtime - 2840140800;
$TimeNow = $TimeFrom1990 + 631152000;
// set the system time
$TheDate = date("m/d/Y H:i:s", $TimeNow + $time_adjustment);
$success = exec("$date_app -s \"$TheDate\"");
// set the hardware clock (optional) - you may want to comment this out
exec("$clock_app --systohc");
echo "The server's date and time was set to $success\n";
} else {
echo "The system time could not be updated. No time servers available.\n";
}
?>
|
This page has been viewed 6,900 times |
|