Linux-Magazin: Syslog
Teil 3: Der Kernel-Log-DämonNicht nur Systemprogramme nutzen Syslog, um Meldungen zu verschicken. Der Linux-Kernel selbst macht ebenfalls von dieser Möglichkeit Gebrauch. Die Nachrichten werden hier zusätzlich vom klogd verarbeitet, bevor sie an den syslogd weitergeschickt werden. Dieser Teil behandelt speziell den Kernel-Log-Dämon sowie Kernel-Logmeldungen. |
|
Wie der Name schon andeutet, verarbeitet der klogd eine spezielle Sorte von Syslog-Nachrichten. Der Kernel selbst bedient sich der Syslog-Methode, um Meldungen zu verteilen. Diese Nachrichten gelangen jedoch nicht direkt an das Syslog-System, sondern werden zuerst vom Kernel-Log-Dämon verarbeitet und dann weitergeschickt.
Der Kernel-Log-Dämon liest die Meldungen vom Kernel und dekodiert zuerst dessen Priorität. Anhand dieser entscheidet er, wo sie ausgegeben werden. Ein Großteil der Kernel-Meldungen wird normalerweise gleich auf der Konsole ausgegeben und parallel an den syslogd geschickt. Dieses Verhalten läßt sich steuern.
Der klogd übernimmt noch eine weitere wichtige Funktion. Er ist in der Lage, die Nachrichten zu dekodieren und Funktionsnamen anzuzeigen, die der Kernel bei einer allgemeinen Schutzverletzung (der berühmte Oops) erzeugt. So können Entwickler direkt sehen, wo der Fehler aufgetreten ist und dadurch das Problem leichter angehen. Weitere Dekodierungen können anschließend mit dem Programm ksymoops vorgenommen werden, welches im Kernel-Sourcebaum enthalten ist.
Um dieses zu erreichen, benötigt der klogd eine Tabelle mit Adressen von Funktionen und Variablen im laufenden Kernel. Diese wird seit langem am Ende eines jeden Kernel-Compiliervorgangs erzeugt und in der Datei System.map gespeichert.
Beim Start liest der klogd diese Tabelle ein. Er sucht sie in /boot/System.map und /System.map. Auf einem Debian GNU/Linux-System wird zusätzlich die Kernelversion an den Dateinamen angehängt (z.B. /boot/System.map-2.0.31), da sich dieses als Quasi-Standard herausgebildet hat.
Schwierig wird die Situation, wenn Kernelmodule ins Spiel kommen. Der Kernel lädt diese nämlich nicht unbdingt immer an der gleichen Stelle. Die Position ist abhängig davon, welche Module bereits geladen wurden und wie die Speicherorganisation aussieht. Zudem kann es passieren, daß Module wieder ausgeladen und durch andere ersetzt wurden. Die Zuordnung von Adressen ist dann nicht so einfach.
Aber auch hier hat der Autor vorgesorgt. Jedesmal, wenn ein Modul hinzugefügt oder entladen wird, sollte dem klogd ein Signal geschickt werden, damit dieser seine Symboltabelle überprüft. Dieses sollte von aktuellen Versionen der modutils erledigt werden.
| Tabelle 1: Parameter vom klogd | |
| Parameter | Wirkung |
| -c n | Setzt den "Console-Level", anhand dessen entschieden wird, welche Nachrichten auf der Konsole angegeben werden. |
| -d | Schaltet Debugging an. Dabei werden ziemlich viele zusätzliche Informationen erzeugt. |
| -f name | Schreibt die Nachrichten in die Datei name anstatt sie per Syslog weiterzuleiten. |
| -i | Schickt ein Signal, welches bewirkt, daß die Modul-Symbole neu geladen werden.. |
| -I | Schickt ebenfalls ein Signal, welches jedoch zur Folge hat, daß die gesamte Symboltabelle neu eingelesen wird. |
| -n | Schaltet den Dämon nicht automatisch in den Hintergrund, was extrem wichtig ist, wenn er vom Init-Prozeß und nicht per /etc/init.d gestartet wird. |
| -o | One-Shot-Mode. Der klogd liest alle ausstehenden Nachrichten, verarbeitet sie und terminiert. |
| -p | Paranoia-Mode. Mit diesem Argument wird der Dämon gezwungen, die Symboltabelle für jeden Oops neu einzulesen. |
| -s | Zwingt den klogd die Syscall-Schnittstelle zu benutzen, um die Kernel-Nachrichten zu lesen, anstatt direkt im /proc-Dateisystem zu lesen. |
| -k file | Die angegebene Datei wird als Symboltabelle geladen. |
| -v | Druckt die Versionsnummer und beendet sich. |
Nachricht von Sam
Jeder hat sie schon einmal gesehen, die Kernelmeldungen. Beim Booten eines Linux-Systems erzeugt der Kernel oft rund 50 Zeilen an Meldungen, die auf dem Bildschirm ausgegeben werden. Nachdem die ersten Systemprogramme gestartet wurden, erzeugen diese zusätzlich normale Syslog-Meldungen.
Weitere Nachrichten werden vom laufenden System erzeugt, wenn z.B. ein Kernelmodul hinzugefügt oder entladen sowie wenn ein weiteres Dateisystem gemountet wird. Bei den meisten Distributionen werden diese Meldungen auf der Konsole ausgegeben (SuSE Linux bildet hier eine Ausnahme, dort werden diese Meldungen unterdrückt).
Wie eingangs erwähnt, läßt sich dieses Verhalten mit dem klogd steuern. Wie normale Syslog-Nachrichten, enthalten auch Kernelmeldungen normalerweise Prioritäten. Anhand dieser kann vom klogd entschieden werden, ob die Meldung auf der Console ausgegeben werden soll oder nicht.
Die Voreinstellung des Kernels besagt, daß alle Meldungen mit einer Priorität 'info' oder höher (numerisch kleiner als 7) auf der Konsole ausgegeben werden. Die numerischen Werte für Prioritäten sind die gleichen, die auch der syslogd (siehe erster Teil dieses Workshops) verwendet. Sie sind in /usr/include/sys/syslog.h dokumentiert.
Mit der Option -c kann getriggert werden, wieviel auf der Konsole ausgegeben wird. Diese Option verlangt eine Zahl als Argument, eine numerische Priorität. Es werden fortan nur Kernelmeldungen mit höherer Priorität (bzw. einem numerisch niedrigeren Wert) auf der Konsole angezeigt.
Viele Meldungen vom Dateisystem (VFS) sind z.B. normalerweise für den Benutzer unwichtig und es würde reichen, wenn sie nur per Syslog verbreitet würden. Viele dieser Meldungen werden vom Kernel selbst als Debugmeldung eingestuft. Mit einem geänderten Wert lassen sie sich von der Konsole fernhalten.
Mit
klogd -c 5
werden nur noch alle Kernelmeldungen mit Priorität "warning" und höher auf der Konsole angezeigt. Diese Einstellung sollte normalerweise ausreichend sein. Diese Option betrifft nicht das Weiterleiten ans Syslog. Der syslogd empfängt sie lokal und speichert bzw. reicht sie weiter.
Die vom Kernel erzeugten Nachrichen enthalten, wenn überhaupt, nur eine Priorität, jedoch keinen Typen. Der klogd ergänzt die sie daher um den Typen "kernel" und ggf. um die Priorität "debug", bevor er sie an Syslog weiterreicht.
Im Kernel
Wie aber sieht es im Kernel aus? Das Syslog-System ist im Kernel nicht bekannt, zudem funktioniert es während des Bootens noch nicht. Beim Start des Kernels (oder eines Moduls) werden jedoch die meisten Kernelmeldungen erzeugt. Viele Treiber bieten zudem die Möglichkeit, zu Debugzwecken mehr Meldungen als normal rauszuschreiben.
Innerhalb des Kernels steht daher die Funktion printk() zur Verfügung, welche die Nachrichten auf der Konsole ausgibt bzw. dem Kernel Logdämon zur Verfügung stellt. Diese Funktion benötigt einen Parameter, wie syslog() ein Format String, der auf weitere angegebene Parameter verweisen kann.
Eine solche Anweisung kann z.B. wie folgt aussehen:
printk("%s: probed %s port.\n",
dev->name, dev->if_port ? "100TX" : "10TP");
Hier wurde keine Priorität angegeben, weshalb die eigentliche Nachricht als Debugmeldung eingestuft und u.U. nicht auf der Konsole ausgegeben wird. Zu sehen ist ein weiterer Unterschied zum Syslog: Hier muß ein Zeilenumbruch angegeben werden. In der Tat schreiben diese Aufrufe zeilenorientiert in einen Puffer, der vom klogd ausgewertet wird.
Es können auch Prioritäten angegeben werden. Allerdings geschieht dieses nicht wie beim Syslog mit einem eigenen Parameter, sondern es wird dem Formatstring eine Stringkonstante vorangestellt. Diese Konstanten sind in kernel.h definiert und heißen ähnlich wie die Syslog-Äquivalente KERN_* statt LOG_*.
Das folgende Beispiel schreibt eine Meldung, die explizit als "error" eingestuft wird.
printk(KERN_ERR "ne.c: Probe of PCI card at %#x failed.\n", pci_ioaddr);
Der Kernel enthält an vielen Stellen derartige Aufrufe, um die Initialisierung der Treiber oder Fehler bekannt zu geben.