HOWTO Syncing Time via internet
From Gentoo Linux Wiki
| Installation • Kernel & Hardware • Networks • Portage • Software • System • X Server • Gaming • Non-x86 • Emulators • Misc |
Contents |
[edit] Introduction
You may want to periodically sync your system-clock with some external timeserver. If you want an accurate time, this howto will not serve you well. You should then rather read HOWTO NTP. This howto is mostly for people whose system clocks get out of sync very rapidly due to a dying CMOS-Battery etc. and who can live with an inaccuracy of up to two minutes (worst case). On this site you will learn how to use the www.worldtimeserver.com timeserver to set your system clock by utilizing the cron job manager and the provided python-script.
The script provided on this page was inspired by a python-script written by Matthias Luebben. The original script can be found here: http://ml81.dyndns.org/~tux/utctime.py His script is a little bit more complex but also allows you to define the format of the time that is returned by the script much in the same way that is possible with commands like date etc. It is however not possible to replace the script provided here with the original script and expect the proceeding instructions to work properly. The original script doesn't provide the appropriate formatting information, so I advise you to stick to the version of the script provided on this site unless you know what you are doing.
[edit] What you need
- A python interpreter (installed by default on Gentoo systems)
- The script provided on this site
- A cron entry to run the script at specified intervalls
- A (preferrably permanent) connection to the internet
[edit] The script
Save the following script onto a directory that is contained in the $PATH variable of user root. /usr/sbin or even better /usr/local/sbin are both good locations for this purpose. Choose an appropriate name like ut.py (update time) or whatever makes sense to you. The following instructions assume that you have called the script ut.py and saved it into the /usr/local/sbin directory. Keep this in mind when you enter the absolute path to the script and modify it to suit the location where you put ut.py on your system. You can verify whether a directory is contained in $PATH by issuing echo $PATH.
localhost ~ # echo $PATH
Remember that the script must be executable. You achieve this by running following command
chmod a+x /usr/local/sbin/ut.py
| File: /usr/local/sbin/ut.py |
#!/usr/bin/python
##################################################################################
# Name: ut.py (update time)
# Version: 0.4
# Purpose: Extract UTC-time from http://www.worldtimeserver.com/
# Author: Mehdi Salem Naraghi. (inspired by ucttime.py by M. Luebben.)
# Modified by:
# Created: 18.12.2005 (dd.mm.yyyy)
# Copyright: Copyright (C) 2005-2006 M. Mehdi Salem Naraghi <momesana@yahoo.de>
# License: Distributed under the terms of the GNU General Public License v2
###################################################################################
import urllib2, re, sys, time, string, os
# ======================= FUNCTIONS ========================
def getLocalTime():
utc = time.gmtime()
localTime = (hour, minute, day, month, year) = (str(utc[3]), str(utc[4]), str(utc[2]), str(utc[1]), str(utc[0]))
return list(localTime)
#-------------------------------------------------------
def getServerTime():
try:
url = urllib2.urlopen( \
"http://www.worldtimeserver.com/current_time_in_UTC.aspx")
html = url.read()
except:
print "error: downloading date/time website " \
"from www.worldtimeserver.com"
sys.exit(1)
mtbl = {"January" : '01', "February" : '02',
"March" : '03', "April" : '04',
"May" : '05', "June" : '06',
"July" : '07', "August" : '08',
"September" : '09', "October" : '10',
"November" : '11', "December" : '12'}
patTime = r"""
UTC/GMT\s+is\s+
(?P<hour>\d+) # hour
:
(?P<minute>\d+) # minute
\s+on\s+\S+,\s+
(?P<month>[A-z]+) # month
\s+
(?P<day>\d+) # day
,\s+
(?P<year>\d+) # year
"""
serverTime = [hour, minute, day, month, year] = \
list(re.compile(patTime, re.VERBOSE).search(html).group('hour', 'minute', 'day', 'month', 'year'))
serverTime[3] = mtbl[serverTime[3]]
return serverTime
#-------------------------------------------------------
def needsUpdate(lt, st):
#compare Date and hour
if not ((int(lt[0]) == int(st[0])) and \
(int(lt[2]) == int(st[2])) and \
(int(lt[3]) == int(st[3])) and \
(int(lt[4]) == int(st[4]))):
return True
#compare minute
if (int(lt[1]) - int(st[1]) > 1) or (int(st[1]) - int(lt[1]) > 1):
return True
else:
return False
#-------------------------------------------------------
def time2str(st):
return st[3]+st[2]+st[0]+st[1]+st[4]
# ======================== MAIN =========================
serverTime = getServerTime()
getServerTime()
if needsUpdate(getLocalTime(), serverTime):
print "performing update"
os.system('date -u ' + time2str(serverTime))
else:
print "skipping update"
|
[edit] Testing the script
Issue ut.py (or whatever you called the script) on the command line.
localhost ~ # ut.py performing update Mi Feb 22 21:57:00 CET 2006
If the system-clock is already accurate enough the output will be like this:
localhost ~ # ut.py skipping update
You could now update the time of your system clock by issuing following command (as root):
ut.py
or
/usr/local/sbin/ut.py
This would set the system's UTC (GMT) time to the value returned by ut.py. The utc time may differ from your local time and that's perfectly alright because your system calculates the local time by adding or subtracting an offset to/from the utc time. In Germany for example, setting the system clock to utc-time 21:48 results in the local time 22:48. The system takes care of that, so you don't need to worry about it. For UTC to work properly remember to set the /etc/localtime symlink to your location. The different location categories can be found under /usr/share/zoneinfo/. To set the local time to that of Germany (Europe > Berlin) you would do following:
localhost ~ # ln -sf /usr/share/zoneinfo/Europe/Berlin /etc/localtime
You can verify this with:
localhost ~ # ls -l /etc/localtime lrwxrwxrwx 1 root root 33 Jan 1 06:32 /etc/localtime -> /usr/share/zoneinfo/Europe/Berlin
The script decently gets the job done but always having to run this command in order to update the time is pretty tiresome and annoying. It would be nice to automate this task so it is carried out by the system auto-magically. Cron enables us to do just this. Read on to find out how this can be done.
[edit] Setting up cron the CLI way
Since doing this requires a little bit of knowledge about cron I refer you to the cron man/info pages and following Gentoo howtos that give you a first insight into cron:
A very simple setup that would sync the clock once every hour would be achieved like this: First you have to create a cron-file (with .cron as suffix) and copy it into the corresponding cron directory. For a script that is executed once every hour you would copy the cron-file to /etc/cron.hourly/.
create a file with following content in /etc/cron.hourly:
| File: /etc/cron.hourly/updatetime.cron |
#! /bin/sh python /usr/local/sbin/ut.py |
make it executable with:
chmod a+x /etc/cron.hourly/updatetime.cron
In order to have more controll you will have to become more intimate with cron, in which case I suggest you to read the above mentioned cron resources and also google for more tutorials. I advise you to use kcron for this task though, at least when you are not a cron wizard. ;)
[edit] Setting up cron using Kcron
Start Kcron as user root and click on the (System Cron) entry in the displayed TreeView. The System Cron entry has probably two subentries:
- Tasks
- Variables
What we are interested in is the Tasks entry. You need to rightclick it and select 'New'. This will create an new Task and pop up a dialog in which you can set its properties. following Entries need to be modified:
- Run as --> set this to root
- Program --> set this to: /usr/local/sbin/ut.py
- The "Enabled" Checkbox must be checked.
- The "Run every day" entry in the "Daily" groupbox must also be checked.
- In the "Hours" & "Minutes" groupboxes you can set the intervals you wish the program to be executed at.
Now click ok and save the changes with the 'Save' button in the toolbar or by selecting File > Save from the menubar. This is important since the changes are not set to effect before you save them. Check to see whether the Run as setting is set right. My Kcron wouldn't set it correctly unless I closed and relaunched kcron and edited those entries again.
[edit] Visual Guide for kcron setup
[edit] Troubleshooting
- You receive the following error:
Traceback (most recent call last): File "/usr/local/bin/ut.py", line 82, in ? serverTime = getServerTime() File "/usr/local/bin/ut.py", line 56, in getServerTime serverTime = [hour, minute, day, month, year] = \ AttributeError: 'NoneType' object has no attribute 'group'
This was solved by a restructuring of the www.worldtimeserver.com page. The solution is to either change the url in the urlopen() function of the scribt to http://www.worldtimeserver.com/current_time_in_UTC.aspx instead of http://www.worldtimeserver.com or using the newest version of the script which already incorporates the fix. Thanx to proteus for reporting.
- You can see whether the script was run correctly or not by checking the sytemlogs. With metalog you find cron's logging information in /var/log/everything/current.
Here is an example:
| Code: Output of tailf /var/log/everything/current |
... Dec 25 23:05:01 [cron] (root) CMD (/usr/sbin/ut.py) ... Dec 25 23:10:01 [cron] (root) CMD (/usr/sbin/ut.py) ... |
- Updates to the System may delete the cron entry when the cron config files are overwritten. In case this happens, you have to create the cron entry again.
- The script may cause Amarok, kaffeine and other players to stall for a few seconds everytime the script is run. This is the case when you are using the Xine-Engine for playback. Using GStreamer etc. on the other hand does not cause any problems. But since the script only modifies the sytem-clock if the difference between the two is higher than two, this doesn't happen very often. Actually it should only happen once everytime you boot your system.
