Voor het beheren van servers en netwerken is het bijhouden van de juiste tijd van essentieel belang. Om een simpel voorbeeld te geven: het analyseren en vergelijken van logfiles wordt een stuk lastiger als je er niet van op aankan dat de gelogde tijdstippen correct zijn.
Meestal wordt het Network Time Protocol (NTP) gebruikt om servers en actieve netwerkcomponenten te synchroniseren met een (externe) tijdserver, bijvoorbeeld die van de eigen internetprovider of van het Network Time Project.
Maar je kan ook een eigen tijdserver configureren. Om te beginnen heb je een DCF-ontvanger nodig, die het tijdsein van de zender in Mainflingen (Duitsland) kan ontvangen. (Er bestaan overigens ook GPS-ontvangers.)
Een voorbeeld van een zo’n DCF-ontvanger is de Expert mouseCLOCK USB II van Gude. In deze blogpost laat ik zien hoe je deze vrijwel out of the box kan configureren op een Linuxserver (Ubuntu 12.04 LTS).
Vreemd genoeg geeft Gude op de eigen wikipagina wat verwarrende aanwijzingen, die suggereren dat je de ntp-daemon zelf zou moeten patchen en compileren. Dat is echter niet het geval.
Stap 1: installeer ntp
$ sudo apt-get install ntp
Stap 2: creëer een stabiele symlink naar de DCF-ontvanger
Wanneer je de mouseCLOCK aansluit op een USB-poort van de server, maakt het systeem een link aan onder /dev, bijvoorbeeld /dev/ttyUSB0. Het volgnummer is afhankelijk van welke andere USB-apparaten zijn aangesloten en op welke USB-poorten. Bij de configuratie wil je niet van dat “toeval” afhankelijk zijn, dus gebruik je udev om te zorgen voor een vaste symlink naar het juiste device.
$ cat /etc/udev/rules.d/mouseclock.rules
KERNEL=="ttyUSB*", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="e88a", SYMLINK+="refclock-%m"
Simpelweg herstarten van udev werkt niet of niet altijd. Jammer, dan toch maar de server herstarten.
Controleer of de symbolische link /dev/refclock-0 nu bestaat. Zo niet, gebruik dan lsusb om te zien of de mouseCLOCK wel “gezien” wordt en udevadm om de attributen te controleren:
$ lsusb
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 006 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 006 Device 002: ID 0403:e88a Future Technology Devices International, Ltd Expert mouseCLOCK USB II
$ udevadm info --name=/dev/ttyUSB0 --attribute-walk
Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.
looking at device '/devices/pci0000:00/0000:00:1d.1/usb6/6-2/6-2:1.0/ttyUSB0/tty/ttyUSB0':
KERNEL=="ttyUSB0"
SUBSYSTEM=="tty"
DRIVER==""
looking at parent device '/devices/pci0000:00/0000:00:1d.1/usb6/6-2/6-2:1.0/ttyUSB0':
KERNELS=="ttyUSB0"
SUBSYSTEMS=="usb-serial"
DRIVERS=="ftdi_sio"
ATTRS{latency_timer}=="1"
ATTRS{port_number}=="0"
looking at parent device '/devices/pci0000:00/0000:00:1d.1/usb6/6-2/6-2:1.0':
KERNELS=="6-2:1.0"
SUBSYSTEMS=="usb"
DRIVERS=="ftdi_sio"
ATTRS{bInterfaceNumber}=="00"
ATTRS{bAlternateSetting}==" 0"
ATTRS{bNumEndpoints}=="02"
ATTRS{bInterfaceClass}=="ff"
ATTRS{bInterfaceSubClass}=="ff"
ATTRS{bInterfaceProtocol}=="ff"
ATTRS{supports_autosuspend}=="1"
ATTRS{interface}=="Expert mouseCLOCK USB II"
looking at parent device '/devices/pci0000:00/0000:00:1d.1/usb6/6-2':
KERNELS=="6-2"
SUBSYSTEMS=="usb"
DRIVERS=="usb"
ATTRS{configuration}==""
ATTRS{bNumInterfaces}==" 1"
ATTRS{bConfigurationValue}=="1"
ATTRS{bmAttributes}=="80"
ATTRS{bMaxPower}=="100mA"
ATTRS{urbnum}=="1391319"
ATTRS{idVendor}=="0403"
ATTRS{idProduct}=="e88a"
ATTRS{bcdDevice}=="0600"
ATTRS{bDeviceClass}=="00"
ATTRS{bDeviceSubClass}=="00"
ATTRS{bDeviceProtocol}=="00"
ATTRS{bNumConfigurations}=="1"
ATTRS{bMaxPacketSize0}=="8"
ATTRS{speed}=="12"
ATTRS{busnum}=="6"
ATTRS{devnum}=="2"
ATTRS{devpath}=="2"
ATTRS{version}==" 2.00"
ATTRS{maxchild}=="0"
ATTRS{quirks}=="0x0"
ATTRS{avoid_reset_quirk}=="0"
ATTRS{authorized}=="1"
ATTRS{manufacturer}=="GUDEADS"
ATTRS{product}=="Expert mouseCLOCK USB II"
ATTRS{serial}=="(het serienummer)"
<knip>
Stap 3: aanpassen AppArmor-instellingen
Nu kan je bijna de NTP-daemon configureren, maar eerst moet deze nog lees- en schrijfrechten voor het device krijgen. Anders grijpt AppArmor in en krijg je foutmeldingen zoals deze in de syslog:
Nov 24 12:33:52 gershwin kernel: [ 34.144834] type=1400 audit(1385292832.757:19): apparmor="DENIED" operation="open" parent=1 profile="/usr/sbin/ntpd" name="/dev/ttyUSB0" pid=1123 comm="ntpd" requested_mask="rw" denied_mask="rw" fsuid=0 ouid=0
Edit de instellingen van AppArmor voor NTP:
$ cat /etc/apparmor.d/tunables/ntpd
# vim:syntax=apparmor
# ------------------------------------------------------------------
#
# Copyright (C) 2002-2005 Novell/SUSE
# Copyright (C) 2011 Canonical, Ltd.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public
# License published by the Free Software Foundation.
#
# ------------------------------------------------------------------
#Add your ntpd devices here eg. if you have a DCF clock
# @{NTPD_DEVICE}="/dev/ttyS1"
#@{NTPD_DEVICE}="/dev/null"
@{NTPD_DEVICE}="/dev/refclock-0", /dev/ttyUSB* rwl
Stap 4: configureren ntp-daemon
Laatste stap is het configureren van de ntp-daemon:
$ cat /etc/ntp.conf
# /etc/ntp.conf, configuration for ntpd; see ntp.conf(5) for help
driftfile /var/lib/ntp/ntp.drift
# Enable this if you want statistics to be logged.
#statsdir /var/log/ntpstats/
statistics loopstats peerstats clockstats
filegen loopstats file loopstats type day enable
filegen peerstats file peerstats type day enable
filegen clockstats file clockstats type day enable
####################
# local clock
server 127.127.1.0
fudge 127.127.1.0 stratum 10
####################
# Expert mouseCLOCK USB II
server 127.127.8.0 mode 19
# Access control configuration; see /usr/share/doc/ntp-doc/html/accopt.html for
# details. The web page <http://support.ntp.org/bin/view/Support/AccessRestrictions>
# might also be helpful.
#
# Note that "restrict" applies to both servers and clients, so a configuration
# that might be intended to block requests from certain clients could also end
# up blocking replies from your own upstream servers.
# By default, exchange time with everybody, but don't allow configuration.
restrict -4 default kod notrap nomodify nopeer noquery
restrict -6 default kod notrap nomodify nopeer noquery
# Local users may interrogate the ntp server more closely.
restrict 127.0.0.1
restrict ::1
Herstart de ntp-daemon.
$ sudo service ntp restart
Houd nu de syslog in de gaten of gebruik het ntpq-commando:
$ ntpq -c cv -c rv
associd=0 status=0020 , 2 events, clk_unspec,
device="RAW DCF77 CODE (Expert mouseCLOCK USB v2.0)",
timecode="------#--##--##---M-S-24---4P---81-p--4--21241---112--1---p",
poll=5, noreply=0, badformat=0, baddata=1, fudgetime1=425.000, stratum=0,
refid=DCFa, flags=0,
refclock_time="d63cb9df.00000000 Sun, Nov 24 2013 17:46:07.000",
refclock_status="TIME CODE; (LEAP INDICATION; ANTENNA)",
refclock_format="RAW DCF77 Timecode",
refclock_states="*NOMINAL: 00:03:08 (65.05%); ILLEGAL DATE: 00:01:41 (34.94%); running time: 00:04:49"
associd=0 status=0215 leap_none, sync_lf_radio, 1 event, clock_sync,
version="ntpd 4.2.6p3@1.2290-o Tue Jun 5 20:12:08 UTC 2012 (1)",
processor="x86_64", system="Linux/3.2.0-56-generic", leap=00, stratum=1,
precision=-23, rootdelay=0.000, rootdisp=228.834, refid=DCFa,
reftime=d63cb9c2.7cf2f48f Sun, Nov 24 2013 18:45:38.488,
clock=d63cb9df.fb6cdc10 Sun, Nov 24 2013 18:46:07.982, peer=22581, tc=6,
mintc=3, offset=22.798, frequency=7.164, sys_jitter=141.420,
clk_jitter=29.318, clk_wander=2.331
Tenslotte
Zijdelings hieraan gerelateerd: het boek “Developing Time-Oriented Database Applications in SQL” (door Richard T. Snodgrass, 1999, ISBN 978-1558604360, uitgever Morgan Kaufmann) gaat over het correct werken met tijdstippen en tijdsintervallen in applicaties. Ook als je geen softwareontwikkelaar bent, is dit een erg interessant verhaal.