Debian – Leere resolv.conf nach Neustart

Gerade hatte ich ein denkwürdiges Erlebnis zusammen mit meinem Freund Michael, das uns beide etliche Nerven gekostet hat. Es ging dabei um eine WLAN-Konfiguration auf einem Laptop. Interessanterweise scheiterten wir dabei nicht an der WLAN-Karte, sondern an elementaren Schwierigkeiten mit der lokalen Konfiguration der “/etc/resolv.conf” – also etwas sehr Trivialem.

Michaels Begeisterung für Debian hat bei dem nachfolgend geschilderten Erlebnis doch einen kleinen Knacks bekommen. (Ich persönlich stehe ja eh’ mehr auf SuSE – eine Vergleichsinstallation auf einem Laptop mit einer Intel 3945 WLAN Karte lief auf Anhieb. Für Debian muss man halt doch immer deutlich mehr Zeit haben und strapazierfähige Nerven mitbringen …. )

WLAN-Karte erfordert Firmware

Michael wollte Debian Lenny auf einem etwas älteren Laptop für seine Tochter installieren – in der begründeten Hoffnung, dass dann auch Debian mit der Hardware zurechtkommen würde … ) Alles verlief denn auch ganz gut, bis es an die Netzwerkkonfiguration seiner WLAN-Karte ging. Es handelte sich um einen schon betagten Intel-Chip, der vom Modul “ipw2200” unterstützt wird. Obwohl das Modul anstandslos geladen wurde, lief dann aber erstmal gar nichts. Vom System wurde kein entsprechendes Netzwerkinterface für die IP-Konfiguration angeboten. Nach einigem Forschen im Internet stellte sich dann heraus, dass man unter Debian auch noch Firmware von der Adresse

http://ipw2200.sourceforge.net/firmware.php

herunterladen muss – ohne diese Firmware läuft die Karte nicht (vergl. mit “http://faq.pathfinderteam.org/index.php/Ipw2200”).

Wichtig ist hierbei übrigens auch, dass zum Einspielen der Firmware ein voller Restart des Systems erforderlich ist. Erst danach wird die Firmware geladen und dass WLAN-Device umfassend über das Kernelmodul angesprochen. Im Anschluss war die Karte denn auch mit “iwconfig” konfigurierbar. Wir kamen nach den üblichen Netzwerkeinstellungen und mit einer manuell konfigurierten “/etc/resolv.conf” schließlich auch anstandslos ins Internet. So weit , so gut …..

Dauerhafte Netzwerkkonfiguration mit “network-admin”

Nun möchte man aber auch unter Debian alle Netzwerkeinstellungen persistent machen. Damit die Netzwerkkonfiguration einen System-Neustart überlebt, müssen natürlich Vorgaben für Startup-Skripte gesetzt und gespeichert werden. Ein zugehöriges graphisches Programm für diese Aufgabe stellt unter Debian “network-admin” dar (siehe etwa http://www.debianadmin.com/debian-networking-for-basic-and-advanced-users.html).

Wohlgemut gingen wir an die Arbeit. Die Default-Einträge für den Rechner und die zugehörigen Domaine muss man natürlich an seine Bedürfnisse anpassen. Gleiches gilt für die Default-Gateway-Adresse. Wir wiesen dem Netzwerk-Interface anfänglich eine statische Adresse zu, die mit dem WLAN-Router kompatibel war. Abschließend legten wir über “network-admin” die Adressen der DNS-Server fest. Ein kurzer Test der Internetverbindung nach einem “/etc/init.d/networking restart” verlief denn auch erfolgreich.

Leere /etc/resolv.conf nach Neustart des Debian-Systems

Dann tauchte aber ein Problem auf, dass wir nur nach stundenlangem Rätseln und herumprobieren lösen konnten: Ein Restart des Systems führte jedesmal zu einer leeren Datei “/etc/resolv.conf” ! Und wer hat schon Lust, nach einem Systemstart immer wieder die DNS-Adressen manuell zu setzen ……

Dass das Netzwerk wegen einer evtl. falschen Runlevel-Konfiguration nicht richtig gestartet wurde, konnten wir nach kurzer Zeit ausschließen. Alles war OK und keine (andere) netzwerkrelevante Konfigurationsdatei wurde beim Systemstart geändert – außer eben der “resolv.conf”. (Die “/etc/network/interfaces” etwa enthält genau die gewünschten Einträge.) Nun
ging das Rätseln los:

  • Lief etwa ungewollt “bind9/named” und überschrieb aus dieser Ecke irgendwas die resolv.conf? Antwort: Nein.
  • Lief “dhcp” und überschrieb evtl. ein DHCP-Server die Einträge? Antwort auch hier wieder: Nein. Der einzige DHCP-Serve im Netz wurde deaktiviert und das dhcp-client-Paket haben wir schließlich explizit vom Laptop deinstalliert. Einen Eintrag “iface ethX …. dhcp” gab es in der Datei “/etc/network/interfaces” auch nicht – sondern korrekterweise “iface ethX inet static”.
  • Wurde etwa beim Starten der der graphischen Oberfläche ein Programm gestartet, dass sich an der resolv.conf zu schaffen machte? Auch das konnten wir ausschließen.

 

Bösewicht “resolvconf”

Später fiel uns dann bei einem Suchlauf auf, dass es auch ein Programm “/etc/resolvconf” und ein zugehöriges Package gab. Bei genauem Hinsehen erkannten wir zusätzlich, dass die Datei “/etc/resolv.conf” eigentlich einen Link zu einer Datei “/etc/resolvconf/run/resolv.conf” darstellte. Das machte uns dann doch sehr misstrauisch. Testhalber haben wir dann das zugrundeliegende Package komplett entfernt:

“apt-get –purge remove resolvconf”.

Und man glaubt es kaum: Danach blieb bei einem Systemneustart die /etc/resolv.conf erhalten !!!!
Resolvconf überschrieb uns beim Systemstart immer unsere DNS-Server-Adressen mit Leereinträgen!

Das muss man erstmal wissen ! Auf meinen SUSE-Systemen gibt es keine Spur eines resolvconf-Paketes. Das Programm “resolvconf” dient unter Debian wohl zur Anpassung von DNS-Einträgen durch verschiedene Programme zur Laufzeit. Die Standard-Datei “/etc/resolv.conf” wird dabei in den angebenen Link verwandelt. Die Zieldatei ist dabei nicht für manuelle Einträge gedacht.

Lösungsmöglichkeiten

Für einfach Systeme, die keinen dynamischen Update der Nameserver-Konfiguration während der Laufzeit benötigen, kann man auf das optionale “resolvconf”-Paket anscheinend verzichten. Wir sind diesen Weg gegangen. Erste Hinweise, was man bei Problemen mit einem laufenden “resolvconf” tun kann, liefert übrigens der Abschnitt zu “resolvconf” unter folgender Adresse:

http://wiki.debian.org/NetworkConfiguration

In unserem Fall hätten wir das Problem wohl auch durch einen zusätzlichen Eintrag in der “/etc/network/interfaces” folgender Art

dns-nameservers ip-adr1 ip-adr2

lösen können. Diesen Eintrag muss man eingerückt hinter dem Gateway-Eintrag platzieren.
(Weitere Hinweise gibt die Datei “/usr/share/doc/resolvconf/README”)

Fazit
Wie gesagt: Das muss man alles erstmal wissen. Ist halt Debian …. nix für einfach gestrickte Gemüter, die an schnelle Lösungen mit Linux glauben wollen …. (sorry, Michael!)

Links:
http://wiki.debian.org/NetworkConfiguration
http://www.debianadmin.com/debian-networking-for-basic-and-advanced-users.html”
http://www.debian.org/doc/manuals/reference/ch-gateway.de.html
http://www.technovelty.de/debian-nameserver-mit-resolvconf-eintragen/

Openoffice – Fremdsprachen-Dictionaries

Meine Frau und ich müssen ab und zu diverse Texte in Norwegisch verfassen. Dabei ist es durchaus sinnvoll, eine entsprechende Rechtschreibkorrektur einzusetzen. Die aktuellen Erfahrung meiner Frau beim Versuch, sich eine norwegische Rechtschreibhilfe unter MS Word 2003 (Windows) und unter Openoffice (Windows und Linux) verfügbar zu machen, gaben Anlass für den nachfolgenden Beitrag.

Die Erfahrung mit dem MS Produkt war folgende:

Es war ein Dokument eines Kunden zu bearbeiten, das mit Word 2003 verfasst worden war und etliche komplexe Tabellen enthielt. Nun wollten wir zusätzlich zur deutschen und englichen Rechtschreibung in aller Naivität norwegische Wörterbücher aktivieren. Fehlanzeige: Für das dt. Office 2003 muss man da (nach Internet-Recherchen) wohl ein Zusatzprodukt (“Proof-Tools”) käuflich erwerben. Das fanden wir ziemlich unerträglich – nach dem Kauf einer teueren Office-Lizenz nachträglich Geschäft durch Erweiterungen für zusätzliche Sprachen zu generieren, halten wir gerade im Zeitalter der sogenannten Globalisierung für wenig einsichtig und eher diskriminierend. Für meine Frau war dies dann wirklich eine weitere Motivation, sich von den Microsoft-Produkten systematisch zu entfernen. Sie fand sich als Norwegerin mit deutscher Office-Version zu Recht benachteiligt.

Also das Experiment: Öffnen des mit Word 2003 verfassten Dokumentes in Openoffice 2.4.1 unter Windows und Linux – sah gut aus ! Nach dem testweisen Speichern unter einem anderen Namen im doc-Format und einem erneuten Öffenen mit Word 2003 war trotz der Tabellen kein Unterschied im Layout erkennbar.

Also weiter mit der Suche nach der norwegischen Rechtschreibung für Openoffice. Erwartungsgemäß gab es keine Option für eine der offiziellen norwegischen Sprachen unter dem Openoffice Menüpunkt “Extras->Optionen->Spracheinstellungen”. Die benötigten Wörterbücher waren weder unter Windows noch unter Linux installiert. Also: Nachforschen im Internet auf der Extensions-Seite für Openoffice – Fehlanzeige. Eine Suche mit “Openoffice norwegian dictionary” führte dann jedoch zum Openoffice Wiki “http://wiki.services.openoffice.org/wiki/Dictionaries”.

Installation und Benutzung unter der Windows Version
Im Wiki gab es denn auch eine brauchbare Installationsanleitung für die aktuelle Windows Version von OpenOffice: Man benutze z.B. unter Openoffice Writer Menüpunkt “Datei->Assistenten->Weitere Wörterbücher installieren”. Dort findet man dann nach einigem Suchen auch eine deutsche Version für die Installation der Wörterbücher. Man kann dann dem Dialog folgen und sich die Wörterbücher direkt aus dem Internet herunterladen und installieren lassen. Danach ist nur ein kompletter Neustart von Openoffice inkl. des Schnellstarters erforderlich, und die norwegische Rechtschreibung steht einem dann zur Verfügung. Mein Frau konnte damit dann die erstellten Dateien inkl. norwegischer Rechtschreibprüfung verarbeiten. Der Kunde hat übrigens den Umweg über Openoffice nicht bemerkt. (Wir haben ihm das aber natürlich mitgeteilt).

Installation und Benutzung unter der Linux Version
Den oben für Windows genannten Menüpunkt für den Installationsassistenten gab es leider unter unserer Openoffice Installation unter Opensuse nicht. Die oben genannte Wiki-Seite erwähnt diesen Punkt leider überhaupt nicht. Die Seite ist insgesamt wenig hilfreich für Linuxer, wenn man nicht gerade Ubuntu verwendet.
Mehr Informationen liefern dagegen die Seiten

http://lingucomponent.openoffice.org/
http://lingucomponent.openoffice.org/auto_instal.html

Die letzte Seite verweist auch auf ein Auto-Installer-Tool, das man sich implementieren kann. Da es aber mit der anstehenden Openoffice Version 3 wieder Änderungen bei der Dictionary Installation geben wird, haben wir das Tool nicht getestet.

Wichtiger erschien uns Folgendes: Die aktuellen OO-Versionen binden über “hunspell” vorhandene “myspell” Dictionaries
ein. Das ist das übliche modulare Konzept für Linux-Applikationen.

Also: rpm-Sprachpakete für myspell suchen und installieren. (Unter Suse bieten Yast/Yum direkt eine sehr große Auswahl an). Interessant für Norwegisch sind die Pakete myspell-norsk-bokmaal-20060428-53.noarch.rpm und myspell-norsk-nynorsk-20060428-53.noarch.rpm. Nach einer Installation mit dem rpm-Paketmanager seiner Wahl und einem Neustart von Openoffice standen diese Wörterbücher dann auch direkt zur Verfügung.

Hinweise zum konkreten (ggf. abschnittsweisen) Einsatz
Grundeinstellungen der Sprache für das Dokument nimmt man über “Extras->Optionen->Spracheinstellungen” vor. Im Dokument selbst benutze man für Absätze oder markierte Abschnitte die Auswahlmöglichkeiten unter dem Menüpunkt “Extras->Sprache->…”, um die Sprachen für gewählte Textbereiche festzulegen. Danach verwendet man F7 oder einen Klick auf das entspr. Icon der Standard-Iconleiste oder den Menüpunkt “Extras->Rechtschreibung”, um die Rechtschreibhilfe zu aktivieren. Für die Aktivierung der Rechtschreibprüfung während der Texteingabe klickt man auf das entsprechende Icon oder legt die Grundeinstellung über “Extras->Optionen->Spracheinstellungen->Linguistik->Optionen” und die dortige entsprechende Checkbox fest. Den Menüpunkt “Automatisch Prüfen” kann man sich über “Extras->Anpassen” auch zum Hauptmenüpunktliste “Extras” dazufügen. Standardmäßig ist er dort nicht vorhanden.

Zur Höhe von Listen bei gefloatetem Inhalt

Wegen einer Nachfrage hier noch ein Kommentar zur Höhenberechnung von dynamisch (!) generierten Listen, in denen die Höhe der Listenelemente und ihrer Inhalte (also irgendwelcher Tags innerhalb der <li>-Tags) nicht vorab bekannt sind und variieren können. Dies betrifft indirekt auch den letzten Beitrag in dieser Blog-Kategorie zur Generierung dynamischer Listen aus Datenbank-Sätzen. Dort hatten wir beschrieben, wie man mit Listen und dem Floaten des Inhalts formatierten Output für Datenbank-Abfragen erzeugen kann.

Eine Kollegin hat nun auf Basis des Beitrags ausprobiert, eine solche Liste unbekannter Höhe zu erstellen, bei der innerhalb der <li> mehrere Elemente (u.a. <div>-Elemente) mit “float:left;” positioniert worden waren. Als sie sich Rahmen um die <li> und das <ul>-Tag zeichnen ließ, war sie sehr erschrocken darüber, dass im Firefox der Rahmen des <ul>-Elements auf einen Strich zusammengezogen erschien. Die Höhe des <ul>-Block-Elements erschien also völlig falsch berechnet.

Komischerweise war das Verhalten im MS IE 7 ganz anders: Hier erschien die Border des <ul>-Tags richtig gezeichnet – also die Höhe des <ul>-Elementes aus den Inhalten der <LI>-Tags richtig berechnet. Warum diese große Diskrepanz zwischen den Browsern? Hat Firefox hier eine Macke? Eine Analyse des Codes zeigt dann dagegen, dass sich der MS IE eigentlich falsch verhielt und Firefox im Wesentlichen richtig!

Ein kurzer Blick auf das <li>-Elemente und die zugehörigen CSS-Anweisungen zeigte (verkürzt) Folgendes:

<ul style="width:30.0em;………border: …… ">
    <li style="width:30.0em; clear:left; float:left; border: ….. ; line-height:1.8em; ….">
        <div style="float:left; ….&quot>graphisches Element</div>
        <div style="float:left; ….&quot><p>mehrzeiliger Text unbekannter Höhe</p></div>
    </li>
    <li style="width:30.0em; clear:left; float:left; border: ….. ; line-height:1.8em; ….">
    ……
    ……
</ul>

Die Listenzeilen wurden schön untereinander dargestellt; leider z.T. mit etwas falschen Abständen, sobald mehrzeilige Elemente auftauchten.

Der erste grundsätzliche Fehler liegt hier zunächst einmal in dem überflüssigen und falschen “float:left” für das <li>-Tag. Dass die Listenelemente überhaupt untereinander dargestellt werden, liegt hier nur an der Breitenbegrenzung des <ul>-Elementes!

Eine Elimination der “float”-Anweisung aus dem <li>-Tag ergab denn schon mal als ersten Fortschritt einen vertikal ausgedehnten Bereich für das <ul>-Element.

Leider hatte das <ul>-Element aber immer noch eine falsche Höhe und auch die Abstände zwischen den <li>-Elementen waren immer noch nicht gleichmäßig. Es hatte also den Anschein, dass die Höhe der <li>-Elemente und damit auch die resultierende Summe für das <ul>-Element nach wie vor falsch berechnet wurden – nämlich so, als ob nur die “line-height” relevant wäre.

Hier kommt nun der interessante Punkt:

Eine “float”-Anweisung hebt den gefloateten Bereich aus dem normalen Inhaltsverlauf (Kontext) des umgebenden Elementes heraus ! Man kann das näherungsweise mit dem Verhalten von absolut positionierten Elementen (z.B. DIVs) in ihrem Parent-Tag (z.B. einem mit “position:relative;” positionierten Container-DIV) vergleichen. Legt man für das umgebende Container DIV eine Höhe und Breite fest, so wird diese im Firefox exakt beachtet; die inneren DIVs ragen aber je nach Position und Größe völlig aus dem umgebenden Bereich heraus. Gleiches gilt für den Inhalt von <p>-Tags: Ist dieser zu groß
und ein Text-Umbruch nicht möglich, so ragt der Text im Firefox aus dem umgebenden Block-Element (DIV) heraus. Dies ist vollkommen CSS-konform. (Der alte MS IE 6 verhält sich hier bei P-Tags noch ganz anders – nämlich so, dass er das umgebende DIV-Tag mit dem<P>-Tag ausdehnt.)

Wo liegt also im obigen Beispiel der Fehler? Warum wird die Höhe der <li>-Elemente nicht richtig berechnet? Antwort: Weil die float-Anweisung nicht innerhalb des <li>-Tags wieder aufgehoben wird!

Das Hinzufügen eines Dummy-Elements zum “Clearen” der float-Anweisung innerhalb des <li>-Tags genügt hierfür! Im obigen Beispiel bringt ein zusätzliches <p style="clear:left; ….">-Tag im <li>-Element alles ins Lot:

<ul style="width:30.0em;………border: …… ">
    <li style="width:30.0em; border: ….. ; line-height:1.8em; ….">
        <div style="float:left; ….&quot>graphisches Element</div>
        <div style="float:left; ….&quot><p>mehrzeiliger Text unbekannter Höhe</p></div>
        <p style="clear:left; font-size:1px; line-height:1px; margin:0; "> </p>
    </li>
    ……
    ……
  </ul>

Natürlich wird dann auch die “clear”-Anweisung für das <li>-Element selbst überflüssig!

Merke also: Eine korrekte Höhenberechnungen von Elementen, die gefloateten Inhalt umschließen, setzt ein Aufheben der Float-Anweisung durch ein abschließendes (Dummy-) Element voraus.

Das gilt natürlich auch und vor allem für die im letzten Beitrag dieser Kategorie diskutierten dynamisch generierten Listen über PHP IT- oder ITX-Templates !

“NIC-Names” unter SuSE

Bei der Vorbereitung auf ein LPI-Zertifikat lernt man den Umgang mit den Befehlen “ifconfig”, “ip” und “iwconfig” in umfassender Weise. Dabei beziehen sich die Befehle allerdings auf vorhandene Interface-Namen, die dem System bereits bekannt sind. Ifconfig kann u.a. die Zuordnung einer IP-Adresse zu einem definierten und benannten Netzwerk-Interface vornehmen. Diese Zuordnung überdauert aber einen Neustart des Systems jedoch nicht.

Trotz Yast kann ein SuSE-Anwender öfter als ihm lieb ist, in eine Situation geraten, in der die Beherrschung von ifconfig nicht mehr genügt und er gerne auch die Antwort auf folgende Fragen wissen möchte:

Wo wird eigentlich unter SuSE der Name eines Netzwerk-Interfaces dauerhaft hinterlegt? Wie wird eine erkannte NIC eigentlich dem jeweiligen Interface-Namen zugeordnet? Wo steht das? Wo und wie hinterlegt SuSE die Netzwerkkonfigurationsdaten dauerhaft zu einem Interface-Namen? Woher erhält das System z.B. beim Startup die Information, dass es zwei Interfaces eth0 und eth1 gibt, de konfiguriert werden müssen? Genau diese Fragen wurden mir heute gestellt – und LPI-Bücher helfen hier nicht wirklich weiter.

Ich versuche nachfolgend zu zeigen, wie man die zugehörigen Konfigurationsdateien und Informationen in einem SuSE-System durch ein wenig Nachdenken und systematisches Stöbern im System finden kann. Bei aktuellen SuSE-Systemen gelangt man dabei unweigerlich zum Verzeichnis “/sys”. Wir gehen daher kurz auch auf seine grundlegende Bedeutung für Kernel 2.6-Systeme ein.

Die Suche nach der Nadel im Heuhaufen

Angesichts der Vielzahl von Konfigurationsdateien, Startup-Skripts und SuSE- bzw. Yast-spezifischen Konfigurationsdateien kann man auch als erfahrener Linux-Anwender bei der Suche nach spezifischen Informationen zu Netzwerkkarten und deren Interface-Namen fast verzweifeln, wenn einem das Internet mal nicht als zusätzliche Informationsquelle zur Verfügung steht.

Um einen Startpunkt zu bekommen, könnte man als erstes geneigt sein, einmal unter “/proc/sys/ipv4/” und genauer unter “/proc/sys/ipv4/conf” nachzusehen. Der Kernel muss ja zumindest wissen, welche Interfaces er im Griff hat. Das ist insofern ein guter Ansatz, als man dort schnell einen Überblick über die aktiven Karten erhält. Übrigens auch über die (virtuellen) Host-Interfaces eines gestarteten VMware-Prozesses, wobei das Linux-Systems als VMware-Host dient:

Netzinterfaces_2

Also irgendwie sind auch dem Kernel die für die Netzwerkkarten vergebenen Namen bekannt. Als SUSE-Anwender weiß man aber auch, dass man die Bezeichnung “eth0” eines Interfaces bereits bei der Einrichtung der Netzwerkkarte über Yast vergeben hat – oftmals schon während der Installation. Zudem bleiben die diesem Namen zugeordnete Konfigurationsvorgaben (z.B. zu DHCP oder einer statischen IP-Adresse) dauerhaft im System erhalten.

Wie gesagt: Der Befehl “ifconfig” kann den Netzwerkinterfaces Konfigurationswerte nur momentan, nicht aber über einen Reboot hinaus zuordnen. Mit ifconfig vergebene Werte überleben einen Neustart des Systems oder des Netzwerkes nicht. (Das kann man leicht ausprobieren!).

Also hegt man die Vermutung, dass es wohl Dateien geben wird, in denen Yast die benötigten Informationen persistent hinterlegt. Diese Informationen müssen dann zwangsläufig bei jedem Systemstart ausgewertet werden und auch dem Kernel verfügbar sein. Um herauszubekommen, woher das System beim Startup Informationen zur Netzwerkkonfiguration und zu Interfaces bezieht, werfen wir deshalb einen Blick in das entsprechende Startup-Skript von SuSE für das Netzwerk.

Dieses Skript finden wir – wie erwartet – unter “/etc/init.d/” als Datei “/etc/init.d/network”. Nach etwas Suchen im Skript stößt man recht bald auf eine Zeile in der das
Verzeichnis

/etc/sysconfig/network

aufgesucht wird.

Das Verzeichnis /etc/sysconfig/net

Bei SuSE werden grundlegende Einstellungen zum System im Verzeichnis “/etc/sysconfig” verankert. Tatsächlich gibt es dort denn auch ein Unterverzeichnis “/etc/sysconfig/network” sowie eine Konfigurations-Datei “/etc/sysconfig/network/config”. Unter SuSE’s Yast gibt es zudem ein Werkzeug – den “/etc/sysconfig”-Editor – mit dem man sich die Einträge unter /etc/sysconfig” ansehen und ggf. auch editieren kann. Die Parameter der Datei “/etc/sysconfig/network/config” erhält man im “/etc/sysconfig”-Editor z.B. unter dem Punkt “Network->General”.

Klickt man sich im “Sysconfig-Editor” weiter durch die Hauptpunkte durch, so gelangt man unter “Hardware->Network” auch zu Unterpunkten für die verschiedenen, namentlich definierten Netzwerk-Interfaces (z.B. eth0, eth1,…). U.a. sind hier die zuzuordnenden IP-Adressen hinterlegt. Weitere im “Sysconfig-Editor” definierte bzw. definierbare Parameter sind z.B.:

BOOTPROTO, BROADCAST, ETHTOOL_OPTIONS, IPADDR, MTU, NAME, NETWORK, REMOTE_IPADDR, STARTMODE, USERCONTROL.

Woher nimmt der “Sysconfig-Editor” diese Informationen? Ein kontrollierender Blick in das Verzeichnis “/etc/sysconfig/network” zeigt dann, dass die Vorgaben für das Interface eth0 (bei der Einrichtung der Netzwerkkarte mit Yast2->Netzwerkgeräte->Netzwerkkarte) in die Datei

/etc/sysconfig/network/ifcfg_eth0

geschrieben wurden. Entsprechende Konfigurationsdateien gibt es unter “/etc/sysconfig/network/” natürlich auch für andere NIC-Interfaces.

Aha, über diese Dateien oder über den “Sysconfig”-Editor kann man also unter SuSE IP-Adressen und Broadcast-Adressen für ein Interface (dauerhaft) ändern. Wenn man also im laufenden Betrieb nicht zu “ifconfig” greifen will oder aber Änderungen für ein Interface dauerhaft hinterlegen muss und die erneute Kartenkonfiguration mit “Yast->Netzwerkgeräte->Netzwerkkarten” scheut, so führt auch der Umweg über das Editieren der besagten Dateien zum Ziel. Im laufenden Betrieb muss man aber nach den Datei-Änderungen (über den “/etc/sysconfig”-Editor) den Befehl “/etc/init.d/rcnetwork restart” aufrufen, um die Änderungen konkret auf die vorhandenen NICs anzuwenden.

Die Startup-Skripts für das Aufsetzen des Netzwerkes greifen also auf die Interface-spezifischen Dateien vom Typ “/etc/sysconfig/network/ifcfg_ethx” zurück. Natürlich macht auch dieses Startup-Skript sich bei der Konfiguration des jeweilige Interfaces intern die Möglichkeiten von ifconfig(oder ip) zu Nutze. (Dies erkennt man, wenn man die Logik des Startup-Slripts weiter verfolgt.)

Nun führen aber Konfigurationsdateien wie “/etc/sysconfig/network/ifcfg_eth0” die Bezeichnung des Netzwerkinterfaces bereits im Namen! Die Datei wurde bei der Konfiguration der NIC erzeugt. Zu diesem Zeitpunkt war natürlich klar, um welche Hardware es sich handelt. Wie weiß das System aber im Nachhinein, welche Interface-Bezeichnung welcher NIC (welchem physikalischen Gerät) zuzuordnen ist? Wo wird also festgeschrieben, welche Netzwerk-Geräte und -Interfaces es im System gibt und welche Namen diesen Interfaces zugeordnet wurden ?

Wir werfen erneut einen Blick in die Startup-Datei “/etc/init.d/rcnetwork restart”. Nach weiterem Scrollen werden wir fündig (Opensuse 10.X):

Zum Durcharbeiten aller Netzwerkinterfaces wird (falls der “Networkmanager” nicht benutzt wird), die Variable “AVAILABLE_IFACES” herangezogen. Ein wenig weitere Forschungsarbeit zeigt schließlich, dass die Variable “AVAILABLE_IFACES” nach Durchlaufen eines Analyse-Loops über den Inhalt des Verzeichnisses

/sys/class/net/

festgelegt wird.

Von /sys/class/net zum sysFS

Tatsächlich zeigt ein Blick in das Verzeichnis “/sys/class/net/” auf einem meiner Systeme auszugsweise Folgendes:

Netz_interfaces_3

Also: Unsere ursprüngliche Frage, wo im System Informationen zu NIC-Interface-Namen hinterlegt sind, haben wir damit beantwortet: Unter “sys/class/net”.

Wir lernen bei der Gelegenheit jedoch noch ein wenig mehr:

Bei genauerem Hinsehen stellen wir fest, dass es sich bei den Dateien unter “/sys/class/net” um Links handelt, die wiederum auf Device-Dateien unter “/sys” (hier genauer: /sys/pci0000:00) verweisen. Wir erkennen nach einigem Studium ferner, dass sich auch Links aus dem Verzeichnis “/sys/bus/pci” auf die Device-Dateien beziehen. Aha, so langsam wird uns klar, dass das “/sys”-Verzeichnis offenbar essentielle und strukturierte Informationen zu Devices – und nicht nur zu Netzwerkdevices – enthält. Es scheint so, als würden Interface-Klassen separat von den Geräten aufgeführt, aber doch einander zugeordnet.

Ein Blick in “/etc/fstab” zeigt übrigens, dass “sysfs” auf “/sys” gemountet wird. Es handelt sich also um ein regelrechtes Filesystem. Wem nützt sowas? Natürlich u.a. dem Kernel (ab Version 2.6). Es handelt sich um das sog. “sysFS”-System, mit dem Geräte und deren Interfaces organisiert werden. Die sysFS-Organisation wird in den Startup-Skripts von SUSE (ab Vers. 9.1) explizit verwendet.

Generell sind die Unterverzeichnisse im sysFS die Verzeichnisse “/sys/devices/”, “/sys/bus”, “/sys/class” und “/sys/block” wesentlich. Die Verzeichnisse “/sys/devices” und “/sys/bus” entsprechen zwei verschiedenen Sichten auf die im System vorhandene Hardwaregeräte.

“/sys/class” und “/sys/block” enthalten alle “Schnittstellen” (Interfaces) zu konkreten Geräten. Nur diese definierten Interfaces können die Anwendungen des jeweiligen Systems ansprechen. es mag befremdlich wirken, aber “/dev/sdb” ist in diesem Sinne z.B. ein Interface zu einem Speichergerät. Von einem Eintrag in den Schnittstellenunterverzeichnissen “/sys/class” oder “/sys/block” führt ein eindeutiger Verweis auf ein entsprechendes Geräteunterverzeichnis in “/sys/devices” und dort zu einem speziellen Gerät.

Unter “/sys/block” findet man (wie der Name andeutet) Interfaces zu Blockgeräten, “/sys/class” enthält dagegen Interfaces zu zeichenorientierten Geräten. Die Major- und Minor-Nummern der Devices sind jeweils in einer zugehörigen Pseudodatei namens »dev« enthalten.

Aha, durch diese Verweise kann das System also wissen, welche Schnittstelle sich auf welches Gerät bezieht. Wie sieht es nun mit den Bezeichnungen der Netzwerk-Interfaces aus?

Durch die persistente Namensvergabe zu Geräte-Schnittstellen unter “/sys/class/net/*” und die entsprechende Bezeichnung der zugehörigen Datei “/etc/sysconfig/network/ifcfg_*” mit den Konfigurationsvorgaben ermöglicht es SUSE, die Netzwerk-Interface-Konfiguration über die sysFS-Struktur mit einem ganz bestimmten Gerät zu verbinden. Im Kern gilt folgende Zuordnungskette:

Gerät unter /sys/devices/Unterverzeichnis/…/Gerätedatei <<>> Bezeichnetes Interface unter /sys/class/net/*

Bezeichnetes Interface unter /sys/class/net/* <<>> (Netz-) Interfacekonfiguration unter /etc/sysconfig/network/ifcfg_*

Hiermit rundet sich unser Bild zur Netzwerkkonfiguration unter SUSE ab. Neben SUSE-spezifischen Konfigurationsdateien und Startup-Skripts spielt der Einsatz der “sysFS”-Struktur eine essentielle Rolle. Die persistente Namensgebung für die Netzwerkinterfaces spiegelt sich im Verzeichnis “/sys/class/net” wieder. Auf dieses nehmen auch die Startup-Skripts Bezug. Die unter “/sys/class/net” definierten Interfaces
sind dagegen mit konkreten Geräten unter “/sys/devices/….” verbunden.

Links

Wer nun immer noch neugierig ist, der möge sich mit tiefergehenden Geheimnissen des “sysFS”-Filesystems und weiterführend ggf. auch mit “udev” befassen.

Einen ersten Einstieg bieten folgende Adressen:

http://de.opensuse.org/SDB:SUSE_Linux_Geräte-_und_Schnittstellenkonfiguration

http://www.linux-magazin.de/heft_abo/ausgaben/2005/04/knoten_knuepfen/(offset)/2

Resultset-Listen in PHP-IT-Templates

Im Rahmen der Programmierung von Datenbank-Abfragen mit PHP ist man immer wieder mit der Frage konfrontiert, wie man die Ergebnisse in listenartiger Form darstellen soll. Hierbei können u.a. folgende Schwierigkeiten auftreten:

a) Die Länge oder Größe des Inhalts einzelner Felder aus der Datenbank ist zunächst unbekannt. Die einzelnen Listenelemente müssen daher in der Höhe variabel sein.

b) Innerhalb eines Listenelementes hat man oftmals komplexe Unterformatierungen vorzunehmen. So ist das Listen-Aufzählungszeichen darzustellen. Hinzu kommen evtl. Feldbezeichnungen, die vom eigentlichen Feldinhalt abgesetzt werden sollen.

c) Der einzelne Satz der Datenbankabfrage beinhaltet i.d.R. mehrere Felder und entsprechende Inhalte, die pro Satz untereinander aufgelistet werden sollen. Um ein komplettes Resultset einer Datenbank-Abfrage darzustellen, braucht man also mindestens eine zweifach geschachtelte Liste. Damit erschwert sich die Formatierung.

d) Die Darstellung der (geschachtelten) Listen erweist sich bzgl. der Formatierung oft als browserabhängig. Dies gilt im besonderen für die Behandlung von Abständen der Aufzählungszeichen zum linken Rand der Liste wie zum Inhalt des Listenpunktes. Hinzu kommen weitere Standardabstände, die ggf. mühsam korrigiert werden müssen.

Will man die Darstellung einer Datenbankabfrage also etwa nach dem Schema

>

Inhalt des Satzes Nr. 11

*

Feldbezeichner 1
Feldinhalt, Feldinhalt, Feldinhalt
Feldinhalt, Feldinhalt, Feldinhalt
Feldinhalt, Feldinhalt, Feldinhalt
Feldinhalt, Feldinhalt, Feldinhalt
Feldinhalt, Feldinhalt, Feldinhalt
Feldinhalt, Feldinhalt, Feldinhalt
………., ……. , …..
………., ……. , …..

 

*

Feldbezeichner 2
Feldinhalt, Feldinhalt, Feldinhalt
Feldinhalt, Feldinhalt, Feldinhalt
Feldinhalt, Feldinhalt, Feldinhalt
………., ……. , …..
………., ……. , …..

 

>

Inhalt des Satzes Nr. 12

*

Feldbezeichner 1
Feldinhalt, Feldinhalt, Feldinhalt
Feldinhalt, Feldinhalt, Feldinhalt
………., ……. , …..
………., ……. , …..

 

formatieren, so erweist sich der simple Einsatz von “<UL><LI></LI></UL>” oft als unzureichend und – nicht zuletzt wegen der Browserabhängigkeit der Listenformatierung – auch als schwierig.

In vielen Fällen sind neben dem oben dargestellten Elementen pro Satz des Resultsets noch weitere schmuckvolle Bereiche darzustellen: etwa eine Leiste mit Buttons zum Auslösen von Pflegeoperationen für den Datenbank-Satzes oder zur Anzeige seines Status.

Gestern bin ich denn auch bei einem Kunden gefragt worden, ob wir zur Darstellung von solchen Resultsetlisten eigentlich Tabellen verwenden würden. Bzw.: Wie wir diese Probleme generell im Zusammenspiel mit serverseitigem PHP lösen würden.

Hierzu gibt es mehrere Antworten:

  1. Wir verwenden zur Formatierung des HTML-Outputs grundsätzlich Templates – zumeist PEAR IT- oder ITX-Templates. (Smarty-Templates sind natürlich eine genauso gute Alternative). Hierdurch trennen wir die Datenbankinteraktion und evtl. Datensatzmanipulationen im PHP-Skript weitgehend von der Darstellung des Resultsets im Browser ab. (Das erleichtert im nachhinein auch den Schwenk von klassischer PHP-Interaktion mit HTML-Generierung zu moderneren Vorgehensweisen auf der Basis von Ajax-Technologien.)

    Alle nachfolgenden Hinweise zur Formatierung sind somit reine HTML- bzw. CSS-Hinweise für das Template.

  2. Bei der Formatierung des listenartigen Outputs im IT-Template setzen wir in der Regel keine Tabellen mehr ein, da wir deren Handhabung inzwischen eher als unflexibel empfinden. Vielmehr verwenden wir sehr wohl Listentags (<UL>, <LI>).
  3. Für die Listen schalten wir i.d.R. allerdings die Formatierung für linksseitige MARGINs und PADDINGs ab. Per CSS setzen wir solche “MARGINs” und “PADDINGs” auf 0, sowohl im <UL>-Tag wie auch im <LI>-Tag. Auch den “list-style-type” setzen wir i.d.R. auf “none”. Hiermit erzielen wir später eine Kompatibilität der Listendarstellung für praktisch alle gängigen Browser (s.u.).
  4. Grundsätzliche Breiteneinstellungen der Liste nehmen wir im <UL>-Tag und wg. des MS IE auch im <LI>-Tag vor. (Das UL-Element verhält sich grundsätzlich wie ein Block. Nur sieht das das der MS IE nicht so.) Die Höhenvorgabe für die gesamte Liste und auch die einzelnen Listenelemente lassen wir dagegen offen.
  5. Die Abstände zwischen den Listen-Elementen regeln “margin-bottom”-Anweisungen für die <LI>-Tags. Hintergrundsfarben für den gesamten Listenbereich regelt wir manchmal über ein DIV, das die Liste umfasst. Von der “normalen” Listenformatierung bleibt also bislang nur eine Breitenvorgabe und ein vorgegebener Abstand zwischen den Listenelementen übrig.
  6. Die Formatierung innerhalb eines Listenelements gestalten wir grundsätzlich mit DIVs. In das <LI>-Tag der Hauptliste binden wir deshalb zunächst ein Container-DIV (“Satz-Container”) vorgegebener Breite ein. Die Höhe dieses Containers bleibt offen.
  7. Innerhalb des “Satz-Container”-DIVs (in einem <LI>-Tag der Liste für die Sätze) positionieren wir nun ein weiteres DIV (“Header-Container”), das zusätzliche DIVs für den den satzspezifischen
    Header und das Aufzählungszeichen für den Satz aufnimmt. Die Positionierung dieser inneren DIVs im “Header-Container” erfolgt über float-Anweisungen; relative Abstände werden über “margin”-Anweisungen festgelegt. Wichtig ist hier noch, dass ein nachfolgendes Dummy-Element (z.B. ein <p>-Tag) das Floaten im Container wieder aufhebt. Breite und Höhe des Header-Containers können in der Regel fest vorgegeben werden. Zusätzlich dient ggf. eine “margin-bottom”-Anweisung zur Festlegung des minimalen Abstands zu weiteren nachfolgenden DIV-Elementen eines Satzes.

  8. Unterhalb des Header-Containers des Satzes positionieren wir nun eine weiteres DIV (“Container Feldliste”). Der Container “Feldliste” wird relativ (!) zum Header-Container positioniert (ggf. ist ein zusätzl. margin-top festzulegen). Seine Breite ist beliebig vorgebbar, seine Höhe bleibt offen.

    Damit die Positionierung auch richtig erfolgen kann, sollte man diesem DIV (Container Feldliste) zur Sicherheit noch eine Style-Anweisung “clear:both;” mitgegeben. Damit werden die vorhergehenden float-Anweisungen für die Header-Elemente aufgehoben, wenn man dies dort vergessen hat.

  9. Verschachtelte zweite Liste: In den “Container Feldliste” positionieren wir nun erneut eine <UL>-Liste, die dann der Darstellung der Feldelemente eines Satzes aus dem Resultset dient. Auch für diese Liste schalten wir evtl. intrinsische linksseitige margin- und padding-Vorgaben der Browser explizit ab und setzen den “list-style-type:none”. Zudem regeln wir den vertikalen Abstand der Listenelemente durch “margin-bottom”-Vorgaben.
  10. Pro Listenelement der feldbezogenen Liste erstellen wir nun einen weiteren DIV-Container (“Container Einzelfeld”). Auch seine Breite und Margins geben wir vor. Die Höhe bleibt dagegen offen.
  11. In den Container “Einzelfeld” werden nun weitere separate DIVs für ein evtl. Aufzählungszeichen, den Feldnamen und den Feldinhalt gesetzt. Die relative Positionierung der inneren DIVs zueinander erreichen wir erneut per CSS-float-Anweisungen. Die relative Positionierung der inneren DIVs zueinander regeln zusätzliche “margin”-Anweisungen. Auch hier heben wir die float-Anweisung wieder über ein abschliessendes Dummy-Element auf. Keines (!) der inneren DIVs wird also im Container über “position:absolute” positioniert. Es werden nur float- und margin-Anweisungen verwendet.
  12. Die Breite der einzelnen inneren DIVs für den Feldbereich geben wir per CSS vor. Die Höhe des DIVs zur Aufnahme des Feldinhalts lassen wir dagegen im Falle von Textfeldern offen, da die Länge und Größe des Feldinhalts dann ja vorab nicht bekannt ist.
  13. Um das Container-DIV “Einzelfeld” (wegen einer evtl. Rahmung oder Hintergrundsfarbe) an die vorab unbekannte Höhe der inneren DIVs – im besonderen des DIVs für den Feldinhalt anzupassen, ist folgender Schritt wichtig:

    Zusätzlich zu den inneren “gefloateten” DIVS bringen wir ein weiteres relativ positioniertes Dummy-Tag (z.B. ein P-Tag) an, das die “style”-Anweisung “clear:both;” enthält. Ohne diese Anweisung ist die Höhe des Container-DIVs “Einzelfeld” nur auf eine Minimum beschränkt und die gefloateten inneren DIVs ragen über den Minimalbereich des Containers weit hinaus. Das Dummy-Tag ermöglicht als reguläres Inhaltselement des Containers die Höhenbestimmung für das Elternelement, indem es die Float-Anweisungen aufhebt.

Durch diese zweifach verschachtelte Liste und die erwähnten Maßnahmen erreicht man eine sehr schöne und im nachhinein per CSS sehr einfach anpassbare Listendarstellung der Ergebnisse von Datenbankabfragen. Da die eigentliche Formatierung jedes Listenelements inkl. Aufzählungszeichen innerhalb
eines DIV-Containers erfolgt, wird man bzgl. der Listendarstellung der Sätze und der inneren Liste der Felder praktisch browser-unabhängig.

Natürlich lagert man die CSS-Anweisungen für die Listen und die inkludierten DIVs zur besseren Pflegbarkeit in eine separate Datei aus.