Zurück

1.111.6

Verwalten der Systemzeit


Beschreibung: Prüfungskandidaten sollten in der Lage sein, die Systemzeit richtig zu verwalten und die Uhr über NTP zu synchronisieren. Dieses Lernziel beinhaltet das Setzen von Systemdatum und -zeit, das Setzen der BIOS-Uhr auf die korrekte Zeit in UTC, die Konfiguration der korrekten Zeitzone des Systems und die Konfiguration der automatischen Korrektur der Zeit auf die NTP-Uhr.

Die wichtigsten Dateien, Bezeichnungen und Anwendungen:


Linux arbeitet mit zwei verschiedenen Uhren, die beide eine große Rolle spielen, die Hardware-Uhr (oder auch RTC, RealTimeClock, CMOS-Uhr, BIOS Uhr) und die Systemzeit. Um mit Linux und der Uhrzeit korrekt umzugehen müssen diese beiden Systeme genau unterschieden werden.

Die Hardware-Uhr ist ein Uhrenbaustein, der völlig unabhängig vom verwendeten Betriebssystem arbeitet. Es handelt sich um eine batteriegepufferte Uhr, die also selbst dann arbeitet, wenn der Computer ausgeschaltet (und von der Stromversorgung getrennt) ist.

Die Systemuhr von Linux ist eine Software-Uhr, die ein Teil des Linux-Kernel ist und durch einen regelmäßigen Timer-Interrupt gesteuert wird. Diese Software-Uhr zählt die Sekunden, die seit dem 1. Januar 1970 um 0:00 Uhr vergangen sind.

Unter Linux zählt nur die Systemzeit, also die kernelgesteuerte Software-Uhr. Der einzige Punkt, wo die Hardware-Uhr ins Spiel kommt ist der Moment des Systemstarts, wo die Systemzeit gestellt werden muß. Hier wird die Hardware-Uhr gelesen und die Systemzeit entsprechend eingestellt. Danach wird die Hardware-Uhr nicht weiter benutzt bis zum nächsten Systemstart.

Es gibt im Wesentlichen zwei Programme, die benutzt werden um auf die beiden Uhren zuzugreifen:

Bei Unix/Linux-Systemen bestehen jetzt zwei grundsätzliche Möglichkeiten, wie die Uhr gestellt werden sollte. Zum einen können wir die Uhr einfach nach der lokalen Zeit stellen, zum anderen haben wir die Möglichkeit, die Hardware-Uhr (und damit auch die Systemzeit) nach der UTC (Greenwich Mean Time) zu stellen und uns anhand einer entsprechenden Zeitzoneninformation die lokale Zeit daraus ausrechnen zu lassen. Diese zweite Möglichkeit ist heute die, der im Allgemeinen der Vorzug gegeben wird. Auch die Lernziele der LPI102 Prüfung zielen auf diese zweite Möglichkeit ab, also werden wir uns entsprechend daran halten.

Der Vorgang ist eigentlich ganz einfach. Wir stellen die Hardware-Uhr manuell (über das BIOS-Setup) auf Greenwich-Zeit und weisen der Umgebungsvariable TZ (TimeZone) den Wert zu, der unsere lokalen Zeitzone entspricht. Das verbreitete Shellscript tzselect bietet eine Auswahlmöglichkeit für die zur Verfügung stehenden Zeitzonen. In einigermaßen modernen Linuxen besteht zudem die Möglichkeit, in der Datei /etc/timezone die aktuelle Zeitzone einzutragen.

Die moderne Standard-Library von Linux kennt noch eine genauere Methode. Im Verzeichnis /usr/share/zoneinfo befinden sich binäre Informationsdateien für jede Zeitzone der Welt (inkl. Antarktis). Im Verzeichnis /etc kann jetzt ein symbolischer Link mit Namen localtime angelegt werden, der auf die entsprechende Zonendatei zeigt, also z.B. für Deutschland

  ln -s /usr/share/zoneinfo/Europe/Berlin /etc/localtime
Um das zu vereinfachen existiert auf vielen Linuxen ein Script mit Namen tzconfig, das genau die Zeitzone abfrägt und anschließend den Link erstellt.

Ist die Zeitzone richtig eingestellt, so verhalten sich alle Linux-Programme, die mit Uhrzeiten arbeiten, automatisch korrekt. Jetzt können wir z.B. auch unsere Hardware-Uhr oder die Systemzeit stellen und die Programme hwclock und date rechnen aus der angegebenen Lokalzeit und der Information der Zeitzone die Greenwich-Zeit aus und stellen die Uhren entsprechend.

Damit Linux jetzt weiß, daß unsere Hardware-Uhr (und die Systemuhr) auf UTC (Greenwich) eingestellt ist, benutzen wir wieder das Programm hwclock. In einem Init-Script sollte die Anweisung

  hwclock --utc --hctosys
stehen. (Falls die Uhr aber auf lokaler Zeit steht sollte statt --utc eben --localtime eingetragen sein)

date

Der Befehl date ist der normale Weg, wie auf die Systemzeit von Unix zugegriffen werden kann. Er bezieht sich aber immer auf die Systemzeit und nicht auf die CMos-Uhr (RTC Real-Time-Clock).

Als einfachste Form der Anwendung kann date einfach ohne Parameter aufgerufen werden. Dann gibt er die Systemzeit in einem String der Form

Sat Aug 21 14:17:40 MEST 1999

auf die Standard-Ausgabe aus. Das ist aber, gerade für Nicht-Amerikaner, nicht immer die gewünschte Form. Aus diesem Grund bietet date auch die Möglichkeit, eine beliebige Ausgabeform für ein Datum zu erstellen.

Wenn date einen Parameter erhält, der mit einem Pluszeichen (+) beginnt, so interpretiert es die folgende Zeichenkette und ersetzt bestimmte Elemente darin mit den entsprechenden Werten der Systemzeit.

Diese interpretierten Elemente beginnen immer mit einem Prozentzeichen (%) dem ein Buchstabe folgt. So bedeutet etwa das %H die Stunden im 24 Stunden-Modus, %M die Minuten. Wenn wir also nur wissen wollen, wie spät es gerade ist, könnten wir schreiben:

date "+Es ist jetzt %H Uhr und %M Minuten"

Die Anführungszeichen sind nötig, weil in unserer Zeichenkette Leerzeichen enthalten sind. Die Ausgabe des Befehls wäre jetzt etwas in der Art:

Es ist jetzt 14 Uhr und 25 Minuten

Eine genaue Darstellung aller unterstützter Parameter ist in der Handbuchseite aufgeführt.

Der Systemverwalter kann mit dem Befehl date auch die Systemuhr stellen, allerdings wird nur die Systemzeit, nicht die CMos-Zeit verändert. Dazu gibt es zwei Möglichkeiten:

  1. Dem Kommando date folgt ein Parameter in der Form MMDDhhmm, also eine Zeichenkette, deren erste zwei Zeichen die Monatszahl (01-12) enthält, die nächsten zwei den Tag des Monats (01-31), die nächsten die Stunden (00-23) und die letzten die Minuten (00-59). Optional kann die Zeichenkette auch noch eine zwei oder vierstellige Jahreszahl und danach, durch einen Punkt getrennt die Angabe der Sekunden (zweistellig) enthalten. (MMDDhhmmYYYY.ss)
  2. Das Kommando date wird mit dem Schalter -s und einem darauffolgendem Datum der Art "Sat Aug 21 14:17:40 MEST 1999" aufgerufen. Das macht in der Regel nur dann einen Sinn, wenn vorher das date-Programm benutzt wurde um diese Zeit abzuspeichern, oder wenn ein date eines Rechners benutzt wird, die Uhren anderer Rechner zu stellen.

Verlässlichere Uhren

Sowohl die Hardware-Uhr, als auch die kernelbasierte Systemuhr sind nicht besonders verlässlich. Zwar bietet die Systemuhr die Möglichkeit über ausgeklügelte Mechanismen wie die Datei /etc/adjtime die Genauigkeit der Zeit zu erhöhen, aber eine wirklich hundertprozentige Zeit ist das auch nicht. Gerade aber bei Servern, die monatelang laufen, summiert sich auch eine kleine Ungenauigkeit auf eine störende Größenordnung. Aus diesem Grund gibt es ein spezielles Protokoll, das eine Synchronisation der Zeit über das Netz ermöglicht: das Network Time Protocol (NTP).

Damit NTP aber vernünftig arbeiten kann, benötigt es eine verläßliche Quelle für die Uhrzeit. Ein NTP-Server wird in der Regel eine Funkuhr besitzen, die eine absolut genaue Uhrzeit für den Rechner zur Verfügung stellt. Diese genaue Zeit kann er jetzt an NTP-Clients weitergeben.

Der Haken an dieser Sache ist, daß Pakete, die über das Netz transportiert werden, auch eine bestimmte Zeit benötigen, von einem Rechner zum anderen zu kommen. In einem lokalen Netz ist dieser Wert vernachlässigbar, im Internet können schon einige Sekunden zusammenkommen, je nach aktueller Verbindungsqualität und der Anzahl der Router, die zwischen den beiden Kommunikationspartnern liegen.

NTP hat auch für diese Frage eine Lösung parat. In der Regel werden nicht nur ein, sondern mehrere Server im Internet als Zeitquelle benutzt. Zu jedem Server wird eine Verbindung aufgebaut, und der Client errechnet sich aktuell, wieviel Zeit eine solche Verbindung dauert. Dazu sendet er eine Anfrage und wartet auf die Antwort. Er misst die entsprechend vergangene Zeit und errechnet sich so ein Mittel der Dauer, die ein Paket vom NTP-Server zu ihm benötigt. So kann er - mit mehreren Servern - auf eine Genauigkeit im Millisekundenbereich kommen, was völlig ausreicht, da unsere Uhr als kleinste Einheit sowieso mit Sekunden arbeitet.

Grundsätzlich geht es in diesem Zusammenhang nicht um den Aufbau eines NTP-Servers, der mit einer Funkuhr ausgestattet ist, sondern um die Anbindung eines Clients an einen existierenden Server. Diese Aufgabe ist sehr einfach zu realisieren, es gibt aber zwei verschiedene Möglichkeiten, einer solchen Anbindung:

Beide Möglichkeiten arbeiten mit dem NTP-Protokoll, aber im ersten Fall arbeitet unser Rechner auch als Server, während er im zweiten Fall nur Client ist.

Zeitsynchronisation mit ntpdate

Wenn es nur gewünscht ist, eine regelmäßige Anpassung der Uhrzeit über einen bestehenden Zeitserver vorzunehmen, so genügt es, mit dem Programm ntpdate die Uhrzeit eines öffentlichen Zeitservers einzuholen. In diesem Fall kann unsere Systemzeit vollkommen verstellt sein, die Uhrzeit (und das Datum) werden einfach vom genannten Server übernommen. Der Aufruf lautet:
  ntpdate Zeitserver
wobei der Zeitserver entweder über seinen Namen oder seine IP-Adresse angegeben werden kann. Eine Liste öffentlicher Zeitserver im Internet ist unter http://www.eecis.udel.edu/~mills/ntp/clock1a.htm erhältlich.

Natürlich bietet es sich an, diesen Aufruf regelmäßig über cron vorzunehmen. Ein entsprechender Eintrag in /etc/crontab könnte also lauten:

  12 * * * *   root  /usr/sbin/ntpdate ntp3.fau.de
Damit würde einmal stündlich (jeweils um 12 Minuten nach der vollen Stunde) die aktuelle Uhrzeit vom Server ntp3.fau.de (einem öffentlichen Zeitserver der Universität Erlangen) geholt und die Systemzeit danach gestellt.

Zeitsynchronisation mit ntpd

Komplexer ist die Aufgabe, die Zeit über einen Daemon zu stellen. Der ntpd oder auch xntpd ermöglicht diese Form der Synchronisation. Der Daemon synchronisiert sich alle 5 Minuten mit einem oder mehreren Zeitservern oder einer lokalen Funkuhr. Seine Konfiguration erhält er über die Datei /etc/ntp.conf. In dieser Datei stehen im einfachsten Fall nur zwei Einträge:
  server ntp3.fau.de
  driftfile /etc/ntp.drift
Die erste Zeile bestimmt den verwendeten Zeitserver, von dem regelmäßig (alle 5 Minuten) die Zeit geholt werden soll. Die zweite Zeile bestimmt eine Datei, die ntpd selbst anlegt und in der die Abweichung der Systemzeit zur realen Zeit gespeichert wird. ntpd ermittelt über Stunden hinweg die Ungenauigkeit der lokalen Zeit und ermittelt einen Wert der Ungenauigkeit in PPM (Parts per Million), der als einfache Fließkommazahl in der Datei /etc/ntp.drift abgelegt wird. Bei jedem Neustart von ntpd kann dann mit diesem Wert gerechnet werden.

Bei der Verwendung von ntpd als Daemon haben wir jetzt neben einer genauen Uhrzeit die Möglichkeit, selbst als Zeitserver für lokale Clients aufzutreten.

Im Gegensatz zur Verwendung von ntpdate darf die Systemzeit unseres Rechners aber nie wirklich größere Abweichungen enthalten. Sobald unsere lokale Zeit mehr als 1000 Sekunden Verschiebung zur Zeit des Servers enthält, weigert sich ntpd die Zeit tatsächlich zu stellen, sondern fordert (in einer Syslog-Meldung) dazu auf, die Zeit manuell zu stellen.

Es ist nicht möglich, beide Techniken auf einmal zu betreiben. Ein Versuch, ntpdate aufzurufen, obwohl ein lokaler ntpd-Prozess läuft, endet mit der Fehlermeldung:

  13 Aug 14:37:05 ntpdate[3209]: the NTP socket is in use, exiting
Beide Programme benutzen den selben Socket, können also nicht nebeneinander existieren. Es ist aber sehr wohl möglich, im entsprechenden init-Script, das ntpd starten soll, einen Aufruf von ntpdate vor dem Aufruf des Daemons zu veranlassen, um sicherzustellen, daß die Systemzeit keine zu große Abweichung aufweist.