[XenoCafe Logo] Click for Homepage
Home Tutorials Forum Blog Advertising Links Contact About



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";
  }
?>


How would you rate the usefulness of this content?

Poor 1
2
3
4
5
6
7
8
9
Outstanding

Optional: Tell us why you rated the content this way.
Characters remaining: 1024
Average rating: 3.50 out of 9.

1 2 3 4 5 6 7 8 9
14 people have rated this content.
This page has been viewed 6,900 times
Copyright © 2004-2010 XenoCafe. All Rights Reserved. XenoCafe is Powered by Linux. Free your mind and your wallet. Switch to Linux.