Das wohl wichtigste Merkmal von eisfair ist die für alle Pakete einheitliche Konfiguration. Deshalb ist die Nutzung der eisfair-Konfigurationsschicht eine absolute Voraussetzung für ein eisfair-Paket.
Im Folgenden wird der Aufbau einer solchen eisfair-Konfigurationsdatei sowie die damit zusammenhängenden Mechanismen beschrieben.
Die aktuelle Konfiguration eines Pakets wird immer in der Datei /etc/config.d/$package gespeichert. Der Aufbau der Konfigurationsdateien ist weiter unten detailiert beschrieben.
Diese Datei wird bei einem eisfair-Paket nicht mitgeliefert, da diese bei der Installation eine eventuell bereits vorhandene Konfiguration einer vorher installierten Version des Pakets überschreiben würde. Bei einer Erstinstallation muss diese aber erstellt werden. Das kann z.B. durch Kopieren der Standardkonfigurationsdatei erfolgen. (Siehe auch Kapitel Paketinstallation)
Die Standardkonfigurationsdatei liegt unter /etc/default.d/$package. Diese Datei muss in einem eisfair-Paket mitgeliefert werden. In ihr muss das Paket deaktiviert sein, d.h. die Startvariable START_$PACKAGE muss auf ,,no`` gesetzt sein.
Bei jedem Editieren einer Konfiguration wird mittels ACFH (Advanced Configuration File Handling) eine Sicherheitskopie der letzten Konfiguration unter /etc/backup.d/$package erstellt. Die Verwaltung dieser Sicherheitskopien erfolgt mittels der ACFH-Funktionalität und muss nicht in jedem Paket einzeln implementiert werden.
Beispiel für eine eisfair-Konfigurationsdatei (Paket foo):
# -----------------------------------------------------------------------
# /etc/config.d/foo - foo configuration parameters
#
# Creation: 2005-02-01 max
# Last Update: 2005-03-06 max
#
# Copyright (c) 2001-2011 the eisfair team, team(at)eisfair(dot)org
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# -----------------------------------------------------------------------
# -----------------------------------------------------------------------
# General settings
# -----------------------------------------------------------------------
START_FOO='no' # start foo: yes or no
FOO_GENERAL_SETTING='60' # time for foo
FOO_ANOTHER_SETTING='Test' # text for foo
FOO_LONG_COMMNET='yes' # you can write long comments by
# using more than one line...
# -----------------------------------------------------------------------
# Second Group
#
# You can give a detailed description of this group inside
# the comment
# -----------------------------------------------------------------------
FOO_ARRAY_N='3' # number of elements in array
FOO_ARRAY_1_ACTIVE='yes' # is element active: yes or no
FOO_ARRAY_1_TEXT='Sample' # some text for an array element
FOO_ARRAY_1_VALUE='12345' # a number for this element
FOO_ARRAY_2_ACTIVE='no' # is element active: yes or no
FOO_ARRAY_2_TEXT='Inactive' # some text for an array element
FOO_ARRAY_2_VALUE='' # a number for this element
FOO_ARRAY_3_ACTIVE='yes' # is element active: yes or no
FOO_ARRAY_3_TEXT='Something' # some text for an array element
FOO_ARRAY_3_VALUE='999' # a number for this element
# -----------------------------------------------------------------------
# End
# -----------------------------------------------------------------------
Damit die Konfiguration mittels eines eisfair-Konfigurationseditors bearbeitet werden kann, ist die Struktur der Konfigurationsdatei zwingend einzuhalten. Im Folgenden werden die einzelnen Blöcke näher beschrieben.
Generell werden spezielle Blöcke mittels der Trennzeilen ,,#-----`` gekennzeichnet.
Vor der eigentlichen Konfiguration steht der Kopfbereich, der im Allgemeinen der GPL-Header ist und einen Verweis auf die GPL enthält, da wohl die meisten Pakete unter der GPL stehen werden.
Am einfachsten sollte der hier angegebene Kopfbereich einfach übernommen und nur die relevanten Inhalte angepasst werden.
Als Fussbereich wird das Ende der Datei mit ,,# End`` gekennzeichnet.
Die gesamte Konfiguration wird in einzelne Gruppen unterteilt. Jede Gruppe wird über den Gruppenkopf näher beschrieben. Dieser wird mittels einer Trennzeile ,,#-----`` eingeleitet und abgeschlossen.
Dazwischen steht in der ersten Zeile der Gruppenname und in den Folgezeilen ein optionaler Kommentar zur gesamten Gruppe. Dort können nähere Angaben zu den in der Gruppe zu konfigurierenden Funktionen gemacht werden (aber hier noch ohne Bezug zur einzelnen Konfigurationsvariable).
Innerhalb der einzelnen Gruppen stehen die Konfigurationsvariablen. Unter diesen nimmt die Startvariable START_$PACKAGE eine Sonderstellung ein. Durch diese Variable wird das gesamte Paket aktiviert bzw. deaktiviert.
Alle anderen Variablen haben die Form $PACKAGE_OPTION, d.h. jede der Variablen bekommt als Präfix den Paketnamen. Die anderen Namensbestandteile werden mittels des Unterstrichs ,,_`` abgetrennt.
Konfigurationsvariablen werden prinzipiell durchgehend gross geschrieben.
Jede Konfigurationsvariable kann mit einem eigenen Kommentar näher beschrieben werden. Dieser Kommentar kann dabei entweder hinter der Variable stehen (mittels mindestens eines Leerzeichens plus einem Kommentarzeichen ,,#`` abgetrennt) oder in der Folgezeile. In diesem Fall muss der Kommentar mittels eines oder mehrerer Leerzeichen eingerückt sein, das Kommentarzeichen darf also nicht in der ersten Spalte stehen.
Mehrzeilige Kommentare sind möglich, dabei dürfen die Kommentarzeichen in keiner Zeile in der ersten Spalte stehen.
Um Optionen anzugeben, die in einer variablen Anzahl auftreten können, müssen mehrere Felder verwendet werden. Diese bestehen aus einer Variable, die die Anzahl der Werte angibt (FOO_ARRAY_N) und den eigentlichen Optionen (FOO_ARRAY_1_TEXT, FOO_ARRAY_1_VALUE). Diese treten dann je nach angegebener Anzahl mehrfach auf.
Um einzelne Ausprägungen auch innerhalb der Liste ausblenden zu können, ohne jedesmal die gesamte Liste umnummerieren zu müssen, empfiehlt sich die Verwendung einer Aktivierungsvariable (FOO_ARRAY_1_ACTIVE). Diese muss dann im paketspezifischen Script geprüft werden.
Mehrdimensionale Felder können in der Form FOO_ARRAY_1_SUBARRAY_2_VALUE) angegeben werden. Dazu müssen dann je Ausprägung der ersten Dimension die Anzahl der Ausprägungen der zweiten Dimension angegeben werden (FOO_ARRAY_1_SUBARRAY_N).
Sobald ein Anwender eine Konfiguration über das eisfair-Menü (über das edit-Script) geändert hat, wird diese auf Gültigkeit überprüft. Dazu wird das Programm eischk benutzt, das im weiteren Verlauf dieses Kapitels näher beschrieben wird.
/etc/check.d/$package
/etc/check.d/$package.exp
/etc/check.d/$package.ext
In der Datei /etc/check.d/$package wird dabei die eigentliche Prüfung mit Abhängigkeiten und Feldern definiert. Dazu stehen die in /etc/check.d/base.exp definierten Regulären Ausdrücke zur Verfügung.
Sofern für die Überprüfung einer eigenen Variable die vordefinierten Ausdrücke nicht ausreichend sind, so können in der Datei /etc/check.d/$package.exp eigene Reguläre Ausdrücke definiert werden. Die Namen dieser eigenen Ausdrücke müssen dabei den Paketnamen als Präfix enthalten (Beispiel: $PACKAGE_VALUES).
In der Datei /etc/check.d/$package.ext können mit einer Scriptsprache zudem weitergehende Prüfungen implementiert werden.
In den neueren Konfigurationseditoren (ECE) können dem Anwender weitergehende Hilfetexte angezeigt werden. Diese müssen dazu in der Datei /var/install/help/$package hinterlegt werden.
Zeilenumbrüche werden in dieser Datei mit dem Tag <br/> gekennzeichnet,
Kommentare können XML-Konform mittels <!-- Kommentar -->
eingefügt werden.
Der Hilfetext jeder einzelnen Variable wird mittels des Tags <help> in dieser Datei hinterlegt.
Die Datei hat damit folgendes Format:
Beispiel für eine eisfair-Hilfedatei (Paket foo):
<!--
# -----------------------------------------------------------------------
# /var/install/help/foo - helptexts for package foo
#
# Creation: 2005-02-01 max
# Last Update: 2005-03-06 max
#
# Copyright (c) 2001-2011 the eisfair team, team(at)eisfair(dot)org
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# -----------------------------------------------------------------------
-->
<help name="FOO_GENERAL_SETTING">
Hier koennen Sie eine Zeitspanne fuer das Paket foo
definieren.<br/>
<br/>
Default: 60
</help>
<!-- Dies ist ein Kommentar -->
<help name="FOO_ARRAY_%_ACTIVE">
Die Konfigurationsvariable FOO_ARRAY_%_ACTIVE dient
zur Aktivierung bzw. Deaktivierung der einzelnen
Eintraege.<br/>
<br/>
Default: yes
</help>
Nach erfolgreicher Prüfung der Konfiguration muss diese aktiviert (,,apply``) werden. Dieser Vorgang wird vollständig im allgemeinen Edit-Script gekapselt.
Für diesen Mechanismus müssen zwei paketspezifische Dateien bereitstehen:
/var/install/config.d/$package.sh
/etc/init.d/$package
Die Datei /var/install/config.d/$package.sh dient dabei zum Generieren der Konfiguration der im Paket verwendeten Software aus der eisfair Konfigurationsdatei. Es handelt sich hier also um das Apply im eigentlichen Sinne.
ACHTUNG
Da eischk die Konfiguration nicht überprüft, wenn START_$PACKAGE='no'
gesetzt ist, darf in diesem Fall kein Neuschreiben der Konfiguration
erfolgen!
Dieses Skript muss im Erfolgsfall den Wert 0 zurückgeben (exit 0). Im Fehlerfall muss ein Wert ungleich 0 zurückgegeben werden. Dies bewirkt, dass der Neustart des Basisdienstes über /etc/init.d/$package nicht ausgeführt wird.
Im Script /etc/init.d/$package muss der Befehl restart unterstützt werden. Dieser Befehl wird beim Aufruf als einziger Parameter übergeben. Bei Aufruf mit restart muss der Dienst neu gestartet bzw. es muss die Konfiguration so eingelesen werden, dass diese wirksam wird.
Weitere Details dazu können in den Kapiteln Menü sowie Bootprozess nachgeschlagen werden.
Das Advanced Configuration File Handling (ACFH) bietet die Möglichkeit, Generationen von Konfigurationsdateien in einem Verzeichnis (/etc/backup.d/) sichern zu lassen. Dies geschieht bei Nutzung des Skripts /var/install/bin/edit automatisch.
Die gesicherten Konfigurationsdateien tragen den Namen
$package.YYYY-MM-DD-HH-MI-SS,
also z.B. inet.2005-03-08-17-57-24.
Die Anzahl der vorzuhaltenden Generationen von Konfigurationsdateien wird bestimmt durch den Wert der Environmentvariablen MAX_BACKUP_CONFIG in der Datei /etc/config.d/environment. Übersteigt die Anzahl der Konfigurationsdateien für ein Paket die in MAX_BACKUP_CONFIG angegebene Anzahl, so wird jeweils die älteste Konfigurationsdatei gelöscht.
Über ein vorbereitetes Menü des ACFH und entsprechende Skripts lassen sich die Funktionen des ACFH aufrufen. An der Stelle inet steht jeweils der entsprechende Paketname.
Beispiel:
Advanced inet-configuration file handling.
1: Restore configuration file from default directory
2: Restore configuration file from backup directory
3: Backup configuration file to backup directory
4: Show difference between current and default configuration
5: Show difference between current and a backup configuration
6: Show difference between default and a backup configuration
7: Show difference between two backup configurations
0: Exit
Select (1-7, ENTER=Return 0=Exit)
Die einzelnen Menüpunkte können allerdings nur dann erfolgreich aufgerufen werden, wenn die entsprechenden Konfigurationsdateien vorhanden sind.
Die Einbindung von ACFH in ein Paket ist mit dem neuen Menüformat (XML-Menü) sehr einfach geworden.
Um für ein Paket das ACFH-Untermenü aufrufen zu können sind nur zwei Zeilen im entsprechenden Paket-Menü notwendig.
<package>$package</package>
<menu file=ssetup.services.advancedconfig.menu">
Advanced configuration file handling</menu>
Das <menu>-Tag muss in einer Zeile stehen.
Über das <package>-Tag wird einerseits die Anzeige im Untermenü (siehe Beispiel oben paketname=inet) gesteuert, andererseits auch für die aufzurufenden Skripte eingestellt, um welches Paket und damit um welche Konfigurationsdateien es sich handelt.
Der über das <package>-Tag eingestellt Paketname wird in der Environmentvariablen $PACKAGE gespeichert. Diese Variable darf nicht anderweitig benutzt oder gar gelöscht werden. Daher steht im ACFH-Untermenü selbst (Datei setup.services.advancedconfig.menu) kein <package>-Tag.
Eine spezielle Situation entsteht, wenn von einem Menü aus mehr als ein ACFH Untermenü für verschiedene Konfigurationsdateien in /etc/config.d/ aufgerufen werden soll.
Dies ist derzeit z.B. im Menü ,,Base configuration`` der Fall. Hier ein Ausschnitt aus dem Menü:
3: Advanced base configuration file handling
4: Advanced environment configuration file handling
Hier wird das ACFH Untermenü sowohl für die Datei /etc/config.d/base, als auch für /etc/config.d/environment aufgerufen.
Über das <package>-Tag ist base als Paketname eingestellt. D.h. der Aufruf für base kann wie oben beschrieben erfolgen.
Für die Behandlung der Datei /etc/config.d/environment muss die Option package="" des <menu>-Tag genutzt werden.
<menu package="environment" file="setup.services.advancedconfig.menu">
Advanced environment configuration file handling</menu>
Das <menu>-Tag muss in einer Zeile stehen.
Um die Quelldatei des Menüs einheitlich zu gestalten, wurde auch der Aufruf des Menüs für die Datei /etc/config.d/base mit der optionalen Option package="" versehen.
<menu package="base" file="setup.services.advancedconfig.menu">
Advanced base configuration file handling</menu>
<menu package="environment" file="setup.services.advancedconfig.menu">
Advanced environment configuration file handling</menu>
Das <menu>-Tag muss in einer Zeile stehen.
Da das alte Menüformat keine Parameter übergeben konnte und auch das Setzen einer Environmentvariablen nicht vorgesehen war, war die Einbindung von ACFH ein wenig komplexer.
Die Einbindung wird hier noch einmal beschrieben, um deutlich zu machen, was beim Umsetzen eines Menüs vom alten Format in das neue Format an ,,Aufräumarbeiten`` notwendig ist.
Um beim alten Menüformat das entsprechende ACFH-Untermenü einbinden und die Skripte erfolgreich aufrufen zu können, existiert das Skript /var/install/bin/add_advancedconfigmenu.
Aufruf: add_advancedconfigmenu [-quiet] <package>
Bei <package> wird der Paketname angegeben. Der Parameter -quiet steuert, ob Ausgaben erfolgen sollen. Das Skript erstellt ein paketeigenes ACFH-Untermenü /var/install/menu/setup.services.$package.advancedconfig.menu sowie eine Reihe von Links mit Prefix $package, die auf die entsprechenden ACFH-Skripts zeigen. Zusätzlich muss die Zeile
/var/install/bin/$package-advancedconfig Advanced configuration file handlingin die entsprechende Menüdatei des Paketes eingetragen werden. Die Angabe muss in einer Zeile stehen.
ACHTUNG
Das Skript add_advancedconfigmenu ist für ein Paket, welches
das neue Menüformat (XML-Menü) nutzt, nicht mehr notwendig.
Zum Löschen des erzeugten paketeigenen ACFH-Untermenüs und der Links existiert das Skript del_advancedconfigmenu
Aufruf: del_advancedconfigmenu [-quiet] $package
Bei $package wird der Paketname angegeben. Der Parameter -quiet steuerte, ob Ausgaben erfolgen sollte.
Genau dieses Skript ist beim Umsetzen eines Paketes vom alten Format in das neue Format z.B. in /tmp/install.sh aufzurufen, um die entsprechenden ,,Aufräumarbeiten`` durchzuführen.
Beispiel:
/var/install/bin/del_advancedconfigmenu -quiet inet
führt die ,,Aufräumarbeiten`` z.B. für das inet-Paket durch.
Um die Konfigurationsfehler in Paketen möglichst auszuschliessen wird für jedes Paket, welches eine Config-Datei besitzt, auch eine EISCHK-Datei angelegt: /etc/check.d/$package. In ihr sind alle Variablen der Konfigurationsdatei einzutragen. Der Aufbau gliedert sich dabei in 4 Spalten, die wie folgt belegt sind:
Diese Spalte gibt den Namen der zu überprüfenden Variable aus der Config-Datei an. Wenn es sich dabei um eine Variable handelt, die mehrmals mit verschiedenen Nummern auftauchen kann, wird an Stelle der Nummer ein Prozentzeichen (%) als Platzhalter in den Variablennamen eingefügt. Mehrere Prozentzeichen zur Überprüfung mehrdimensionaler Arrays sind zulässig. Sollten Variablen nur unter bestimmten Konfigurationsbedingungen benötigt werden, so sind sie als Optional zu kennzeichnen. Dazu wird vor die Variable ein ,,+`` Zeichen vorangestellt. Soll ein gesamtes Array optional sein, dann ist der Zählvariable (z.B. FOO_N) ebenfalls ein ,,+`` voranzustellen. In diesem Fall müssen aber auch die Array-Elemente als optional gekennzeichnet werden.
Beispiele:
optionale Variable:
# Variable: OPT_VARIABLE: VARIABLE_N: VALUE:
+FOO_NAME - - NONE
optionales Element in einem Array:
FOO_N - - NUMERIC
++FOO_%_VALUE1 - FOO_N NONE
FOO_%_VALUE2 - FOO_N NONE
optionales Array:
+FOO_N - - NUMERIC
++FOO_%_VALUE1 - FOO_N NONE
++FOO_%_VALUE2 - FOO_N NONE
optionales mehrdimensionales Array:
+FOO_N - - NUMERIC
++FOO_%_VALUE_N - FOO_N NUMERIC
++FOO_%_VALUE_%_VAL1 - FOO_%_VALUE_N NONE
Bei Bedarf kann in dieser Spalte eine Abhängigkeit zu einer anderen Variable
(OPT_VARIABLE) definiert werden. Dadurch findet eine Überprüfung nur dann statt,
wenn die OPT_VARIABLE auf ,,yes`` steht. Der Name der OPT_VARIABLE
darf keine Platzhalter für Arrays (%) enthalten. Gibt es keine OPT_VARIABLE, ist hier
ein ,,-`` anzugeben.
Ab dem base-Paket v1.3.0 dürfen Platzhalter für Arrays (%) enthalten sein.
Beispiel:
# Variable: OPT_VARIABLE: VARIABLE_N: VALUE:
--------------------------------------------------------------------------------------
EISFAX_ANALOG_USE START_EISFAX - YESNO
EISFAX_ANALOG_N EISFAX_ANALOG_USE - NUMERIC
EISFAX_ANALOG_%_NAME EISFAX_ANALOG_USE EISFAX_ANALOG_N NONE
EISFAX_ANALOG_%_ACTIVE EISFAX_ANALOG_USE EISFAX_ANALOG_N YESNO
EISFAX_ANALOG_%_DEVICE EISFAX_ANALOG_%_ACTIVE EISFAX_ANALOG_N NOTEMPTY
EISFAX_ANALOG_%_SND EISFAX_ANALOG_%_ACTIVE EISFAX_ANALOG_N YESNO
EISFAX_ANALOG_%_SND_TO EISFAX_ANALOG_%_SND EISFAX_ANALOG_N NONE
EISFAX_ANALOG_%_SND_TYPE EISFAX_ANALOG_%_SND EISFAX_ANALOG_N EISFAX_FTYPE
EISFAX_ANALOG_%_PRN EISFAX_ANALOG_%_ACTIVE EISFAX_ANALOG_N YESNO
EISFAX_ANALOG_%_PRN_QUE EISFAX_ANALOG_%_PRN EISFAX_ANALOG_N EISFAX_PQUEUE
EISFAX_ANALOG_%_PRN_TYPE_GS EISFAX_ANALOG_%_PRN EISFAX_ANALOG_N YESNO
EISFAX_ANALOG_%_PRN_DRV EISFAX_ANALOG_%_PRN_TYPE_GS EISFAX_ANALOG_N NONE
Steht in der ersten Spalte eine Variable mit einem Platzhalter % im Namen, so wird hier die Variable angegeben, die die Häufigkeit des Auftretens der Variable definiert. Für mehrdimensionale Array sind auch hier % Zeichen im Namen zulässig. Gibt es keine VARIABLE_N, ist hier ein ,,-`` anzugeben.
Beispiel 1:
# Variable: OPT_VARIABLE: VARIABLE_N: VALUE:
BIND9_N - - NUMERIC
BIND9_%_NAME - BIND9_N DOMAIN
BIND9_%_MASTER - BIND9_N YESNO
BIND9_%_NETWORK - BIND9_N IPADDR
Beispiel 2 - mehrdimensionale Arrays mit optionalen Parametern:
# Variable: OPT_VARIABLE: VARIABLE_N: VALUE:
++BIND9_%_NS_N - BIND9_N NUMERIC
++BIND9_%_NS_%_NAME - BIND9_%_NS_N FQDN
Diese Spalte enthält die Überprüfungrichtlinie des Inhaltes der Variable. Sie sollte im Interesse einer geringen Fehlerquote möglichst exakt die Eingabemöglichkeiten eingrenzen. Dabei kann auf eine grosse Anzahl von fertigen Definitionen zurückgegriffen, aber auch mittels sogenannter ,,Regular Expressions`` eigene erstellt werden.
Folgende Definitionen sind bereits vorhanden:
| Name | Bedeutung | Beispiele
|
|---|---|---|
| NONE | Keine Überprüfung durchführen | |
| NOTEMPTY | Inhalt darf nicht leer sein | 'foo- 12' |
| NOBLANK | Es dürfen keine Leerzeichen enthalten sein | 'foo' |
| ENOBLANK | Kein Eintrag - oder Eintrag wie unter NOBLANK | '' / 'foo' |
| NUMERIC | Nur Zahlen sind zulässig | '1234' |
| ENUMERIC | Kein Eintrag - oder Eintrag wie unter NUMERIC | '' / '1234' |
| DOT_NUMERIC | Zwei Zahlen durch einen Punkt getrennt | '12.5' |
| EDOT_NUMERIC | Kein Eintrag - oder Eintrag wie unter DOT_NUMERIC | '' / '12.5' |
| NUM_HEX | Hexadezimale Zahl - startend mit 0x | '0xff12' |
| NUM_ANY | Zahlen in numerischer oder hexadezimaler Schreibweise | '123' / ''0xff12' |
| YESNO | Nur yes oder no sind erlaubt | 'yes' / 'no' |
| MACADDR | Mac Adresse einer Netzwerkkarte | '00:00:E8:83:72:92' |
| HOSTNAME | Hostname bestehend aus Buchstaben, Zahlen und Bindestrich | 'foo-1' |
| DOMAIN | Domainname inclusive Endung | 'bar.local' |
| EDOMAIN | Kein Eintrag - oder Eintrag wie unter DOMAIN | '' / 'bar.local' |
| FQDN | Vollständiger Internetname - host.domain.location | 'foo-1.bar.local' |
| EFQDN | Kein Eintrag - oder Eintrag wie unter FQDN | '' / 'foo-1.bar.local' |
| OCTET | Zahl im Bereich von 0 bis 255 | '128' |
| IPADDR | Gültige IP-Adresse, bestehend aus 4x OCTET | '192.168.0.128' |
| EIPADDR | Kein Eintrag - oder Eintrag wie unter IPADDR | '' / '192.168.0.128' |
| IPADDRESSES | Eine oder mehrere IP-Adressen durch Leerzeichen getrennt | '192.168.0.1 192.168.0.2 192.168.0.3' |
| EIPADDRESSES | Kein Eintrag - oder Eintrag wie unter IPADDRESSES | '' / '192.168.0.1 192.168.0.2 192.168.0.3' |
| IP_ROUTE | Netzwerk, Netzmaske und Gateway durch Leerzeichen getrennt | '192.168.0.0 255.255.255.0 192.168.0.254' |
| DNS_SPEC | DOMAIN und IP-Adresse durch Leerzeichen getrennt | 'bar.local 192.168.0.1' |
| MASK | Zahl zwischen 0 und 32 | '32' |
| NETWORK | Kombination aus IP-Adresse, Trennstrich und Maske | '192.168.0.0/24' |
| NETWORKS | Ein oder mehrer Netzwerke durch Leerzeichen getrennt | '192.168.0.0/24 192.168.1.0/24' |
| ENETWORKS | Kein Eintrag - oder Eintrag wie unter NETWORKS | '' / '192.168.0.0/24 192.168.1.0/24' |
| MULTIPLE_NETWORKS | Ein oder mehrer Netzwerke durch Leerzeichen getrennt | '192.168.0.0/24 192.168.1.0/24' |
| EMULTIPLE_NETWORKS | Kein Eintrag - oder Eintrag wie unter MULTIPLE_NETWORKS | '' / '192.168.0.0/24 192.168.1.0/24' |
| IPADDR_NETWORK | IP-Adresse und Netzwerk durch Leerzeichen getrennt | '192.168.0.1 192.168.1.0/24' |
| EIPADDR_NETWORK | Kein Eintrag - oder Eintrag wie unter IPADDR_NETWORK | '' / '192.168.0.1 192.168.1.0/24' |
| MAILADDR | Vollständige E-Mail Adresse | 'foo@bar.local' |
| EMAILADDR | Kein Eintrag - oder Eintrag wie unter MAILADDR | '' / 'foo@bar.local' |
| CRONTAB | Crontab Eintrag: Minute Stunde Tag Monat Wochentag | '15 3 * * fri' |
| REL_PATH | Relatives Verzeichnis | 'install/menu' |
| E_REL_PATH | Kein Eintrag - oder Eintrag wie unter REL_PATH | '' / 'install/menu' |
| ABS_PATH | Absolutes Verzeichnis | '/var/install/menu' |
| E_ABS_PATH | Kein Eintrag - oder Eintrag wie unter ABS_PATH | '' / '/var/install/menu' |
| LOG_INTERVAL | Als Werte sind daily, weekly oder monthly möglich | 'daily' / 'weekly' / 'monthly' |
| PORT | Kommunikationsport im Bereich von 1 - 65535 | '3050' |
| ETH_BASE_DEV_NAME | Name der Ethernet Schnittstelle | 'eth0' |
| ETH_DEV_NAME | Erweiterter Name der Ethernet Schnittstelle | 'eth0:3 |
| TR_BASE_DEV_NAME | Name der Tokenring Schnittstelle | 'tr2' |
| TR_DEV_NAME | Erweiterter Name der Tokenring Schnittstelle | 'tr2:1' |
| BR_DEV_NAME | Netzwerk Bridge Schnitstelle | 'br1:2' |
| BOND_BASE_DEV_NAME | Netzwerk Bonding Schnitstelle | 'bond0' |
| BOND_DEV_NAME | Erweiterter Name der Netzwerk Bonding Schnitstelle | 'bond0:1' |
| XEN_BASE_DEV_NAME | XEN Bridge Netzwerk Schnitstelle | 'xen-br0' |
| XEN_BASE_NAME | Erweiterter Name der XEN Bridge Netzwerk Schnitstelle | 'xen-br0:1' |
| DUMMY_DEV_NAME | Platzhalter Schnittstelle (Dummy) | 'dummy0' |
| IP_NET_NAME | Ethernet, Tokenring, Bridge oder Dummy Schnittstelle | 'eth0:2' / 'br1' / 'tr0' / 'dummy0' |
| IP_ROUTE | Netzwerkroute (network netmask gateway) | '192.168.1.0 255.255.255.0 192.168.1.254' |
| IP_ROUTE_CIDR | Netzwerkroute (network/cidr gateway) | '192.168.1.0/24 192.168.1.254' |
| PASSWD | Spezielle Regel, die die Sichtbarkeit im ECE beeinflusst. In der Ansicht wird der Wert der Option mit dem Zeichen '*' maskiert. Die Werteeingabe erfolgt über einen speziellen Dialog zur Passworteingabe. | '**********' |
| READONLY | Spezielle Regel, die die Sichtbarkeit im ECE beeinflusst. In der Ansicht wird der Wert der Option inaktiv dargestellt. Eine Bearbeitung des Wertes wird vom Programm unterbunden. | |
| HIDDEN | Spezielle Regel, die die Sichtbarkeit im ECE beeinflusst. In der Ansicht wird der Wert nicht dargestellt. |
Da auch mit diesen Möglichkeiten nicht jeder Anwendungsfall abzudecken ist, gibt es die Möglichkeit, eigene Überprüfungen zu definieren. Diese werden durch die Buchstaben ,,RE:`` für Regular Expressions eingeleitet.
Beispiel:
# Variable: OPT_VARIABLE: VARIABLE_N: VALUE:
COLOR - - RE:red|green|blue
So kann eine einfache Parameterauswahl realisiert werden. Alle anderen Eingaben als ,,red``, ,,green`` oder ,,blue`` werden abgelehnt. Ein komfortablerer Weg stellt der Einsatz einer /etc/check.d/$package.exp Datei dar. In ihr können neben den Regular Expressions eigene Fehlermeldungen definiert werden.
ACHTUNG
Eigene Regular Expressions in der Datei /etc/check.d/$package.exp müssen
den Paketnamen als Präfix enthalten.
Beispiel:
FOO_COLOR = 'red|green|blue' : 'only red, green or blue are allowed'
In den regulären Ausdrücken können auch Referenzen auf bereits existierende Definitionen enthalten sein. Dadurch ist es einfacher, reguläre Ausdrücke zu konstruieren. Eingefügt werden die Referenzen einfach durch '(RE:Referenz)'.
Beispiel:
FOO_IP_ROUTE = '(RE:IPADDR)[[:space:]]+(RE:IPADDR)[[:space:]]+(RE:IPADDR)'
: 'no valid route specification (network netmask gateway)'
FOO_DOT_NUMERIC = '(RE:NUMERIC).(RE:NUMERIC)'
: 'should be numeric (decimal) with dot e.g. 5.0'
Die speziellen Regeln PASSWD, READONLY und HIDDEN sind lediglich für den ECE von Bedeutung. Für eischk stellen sie keine Einschränkung des Wertebereichs dar. Deshalb werden sie in der Datei /etc/check.d/$package häufig in Kombination mit anderen Regeln verwendet. Beispiel:
Beispiel:
# Variable: OPT_VARIABLE: VARIABLE_N: VALUE:
FOO_DEBUG - - YESNO
FOO_DEBUG - - HIDDEN
Findet die Prüfung einen Fehler, erfolgt die Ausgabe der Fehlermeldung auf folgende Art:
Error: wrong value of variable HOSTNAME: '' (may not be empty)
Error: wrong value of variable MOUNT_OPT: 'rx' (user supplied regular expression)
Beim ersten Fehler wurde der Ausdruck in einem exp file definiert und ein Hinweis auf den Fehler wird mit ausgegeben. Im zweiten Falle wurde der Ausdruck direkt im *.txt File spezifiziert, deshalb gibt es keinen zusätzlichen Hinweis auf die Fehlerursache.
Reguläre Ausdrücke sind wie folgt definiert:
Regulärer Ausdruck: Eine oder mehrere Alternativen, getrennt durch '|', z.B. 'ro|rw|no'. Trifft eine der Alternativen zu, trifft der ganze Ausdruck zu (hier wären 'ro', 'rw' und 'no' gültige Ausdrücke).
Eine Alternative ist eine Verkettung mehrerer Teilstücke, die einfach aneinandergereiht werden.
Ein Teilstück ist ein ,,Atom``, gefolgt von einem einzelnen '*', '+', '?' oder '{min, max}'. Die Bedeutung ist wie folgt:
Ein ,,Atom`` ist ein
Ein Ausdruck mit rechteckigen Klammern bedeutet folgendes
Sehen wir uns das mal an einigen Beispielen an:
Numerisch: Ein numerischer Wert besteht aus mindestens einer, aber beliebig vielen Zahlen. Mindestens ein, aber beliebig viele drückt man mit '+' aus, eine Zahl hatten wir schon als Beispiel. Zusammengesetzt ergibt das:
NUMERIC = '[0-9]+' oder alternativ
NUMERIC = '[[:digit:]]+'
NOBLANK: Ein Wert, der keine Leerzeichen enthält ist ein beliebiges Zeichen (ausser dem Leerzeichen) und davon beliebig viele:
NOBLANK = '[^ ]*'
bzw. wenn der Wert zusätzlich auch nicht leer sein soll:
NOBLANK = '[^ ]+'
Disk und Partition: Gültige Bezeichner für eine Disk beginnen mit hd bei IDE-Disks bzw sd bei SCSI-Disks. Dann folgen Buchstaben von a-z (a für die erste Disk, b für die 2., ...) und bei Partitionen die Zahlen 1-8 (1-4 für die ersten 4 Partitionen, die Primär bzw. Extended (nur eine) sein können und 5-8 für die logischen Partitionen innerhalb einer extended Partition). Die Ausdrücke sehen dann wie folgt aus:
DISK = '(hd|sd)[a-z]'
PARTITION = '(hd|sd)[a-z][1-8]'
Sehen wir uns das ganze nochmal am Beispiel der IP-Addresse an. Eine IP-Adresse besteht aus 4 Octets, die mit einem '.' getrennt sind. Ein Octet kann eine Zahl zwischen 0 und 255 sein. Definieren wir als erstes ein Octet. Es kann
| eine Zahl zwischen 0 und 9 sein: | [0-9] |
| eine Zahl zwischen 00 und 99: | [0-9][0-9] |
| eine Zahl zwischen 100 und 199: | 1[0-9][0-9] |
| eine Zahl zwischen 200 und 249: | 2[0-4][0-9] |
| eine Zahl zwischen 250 und 255 sein: | 25[0-5] |
Da sich die ersten drei Teile stark ähneln, kann man sie zusammenfassen:
Das ganze sind Alternativen, also fassen wir sie einfach mittels '|' zu einem Ausdruck zusammen: '1?[0-9]?[0-9]|2[0-4][0-9]|25[0-5]' und haben damit ein Octet. Daraus können wir nun eine IP-Adresse machen, 4 Octets mit Punkten voneinander getrennt (der Punkt muss mittels backslash gequotet werden, da er sonst für ein beliebiges Zeichen steht). Basierend auf der Syntax der Exp-Files sieht das ganze dann wie folgt aus:
OCTET = '1?[0-9]?[0-9]|2[0-4][0-9]|25[0-5]'
IPADDR = '((RE:OCTET)\.){3}(RE:OCTET)'
Manchmal ist es notwendig, komplexere Überprüfungen durchzuführen. Beispiele für solche komplexeren Dinge wären z.B. Abhängigkeiten zwischen Paketen oder Bedingungen, die nur erfüllt sein müssen, wenn Variablen bestimmte Werte annehmen.
Um diese Überprüfungen durchführen zu können, kann man in /etc/check.d/$package.ext kleinere Tests schreiben. Die Sprache besteht aus folgenden Elementen:
Mit Hilfe dieser drei Funktionen kann man Nutzer warnen, einen Fehler signalisieren oder die Prüfung sofort abbrechen. Das Format sieht wie folgt aus:
Im Text kann man auf Variablen Bezug nehmen, indem man einfach den Namen mit einem vorangestellten '$' oder '%' Zeichen in den Text schreibt (evtl. in eingeschlossen, um den Variablenamen vom umgebenden Text abzugrenzen). eischk versucht den darauffolgenden Text (Ziffern, Zahlen, '_') als Variablennamen zu interpretieren und setzt bei einem vorangestellten '$' den Inhalt der Variablen an dieser Stelle ein, wenn Sie definiert ist, bzw bei einem vorangestellten '%' den vollständigen Namen der aktuellen %-Variable. Sonst steht der originale Text da. Will man wirklich ein '$' oder ein '%' im Text haben, schreibt man '$$' bzw. '%%'.
Benötigt man aus irgend einem Grund eine temporäre Variable, kann man diese einfach mit ,,set var [= value]`` anlegen. Die Variable darf keine Config-Variable sein. Lässt man den ,,= value`` Teil weg, wird die Variable einfach auf ,,yes`` gesetzt, so dass man sie hinterher einfach in einer if-Anweisung testen kann. Wird ein Zuweisungsteil angegeben, kann hinter dem Gleichheitszeichen alles stehen, normale Variablen, indizierte Variablen, Zahlen, Zeichenketten, Versionen.
Will man auf einzelne Elemente einer %-Variablen (eines Arrays) zugreifen, kann man das wie gewohnt mit %_var[index] tun, wobei für jedes % Zeichen ein [ Index ] auftauchen muss.
stat() ermöglicht es, Eigenschaften einer Datei abzufragen. Zur Verfügung gestellt wird im Augenblick lediglich die Grösse einer Datei, andere Attribute sind aber leicht hinzuzufügen. Abfragen sehen wie folgt aus (wobei die verwendeten Parameter nur Beispiele sind):
stat ("unix/Makefile", test)
Danach sind zwei Variablen definiert:
Das könnte dann z.B. so aussehen:
stat ("unix/Makefile", test)
if ("$test_res" == "OK")
then
warning "test_size = $test_size"
else
error "Error '$test_res' while trying to get size of ..."
fi
Oftmals werden Variablen mit mehreren Parametern belegt, die dann in Startup-Scripten erst wieder auseinandergenommen werden. Will man diese bereits vorher auseinandernehmen und Tests mit ihnen durchführen, nimmt man split().
split (string, %_var, character)
Der String kann durch eine Variable, %-Variable oder direkt als String angegeben werden. eischk zerlegt ihn an den Stellen, an denen das Trennzeichen auftaucht und erzeugt je eine Instanz der %-Variablen. Über diese kann man dann hinterher Tests laufen lassen. Steht zwischen zwei Trennzeichen nichts, wird eine Instanz mit einer leeren Zeichenkette als Wert erzeugt. Ausnahme ist ' ', hier werden alle whitespaces konsumiert und keine leeren Variablen erzeugt.
Sollen die bei der Zerlegung entstandenen Elemente in einem numerischen Kontext verwendet werden (z.B. als Index), muss das beim Aufruf von Split spezifiziert werden. Das geschieht durch das zusätzliche Attribut 'numeric'. Der Aufruf sieht dann wie folgt aus:
split (string, %_var, character, numeric)
if (expr)
then
statement
else
statement
fi
Eine klassische if-Konstruktion wie man sie kennt. Ist die Bedingung wahr, wird der then-Teil ausgeführt, ist die Bedingung falsch, wird der else-Teil ausgeführt.
Will man Tests über %-Variablen durchführen, muss man jede einzelne Variable testen. Dazu gibt es das foreach-Statement in zwei Varianten:
foreach loop_var in set_var
do
statement
done
Diese Schleife iteriert über alle %-Variablen, angefangen bei eins bis zum in der dazugehoerigen (in /etc/check.d/$package stehenden) Variable_N stehenden Index n. Die Laufvariable loop_var nimmt dabei die jeweiligen Werte der %-Variablen an.
Das Statement kann dabei eine der oben beschriebenen Funktionen if, foreach, warning, error oder fatal_error sein.
Will man genau eine %-Variable testen, kann man diese mittels var_%$index auswählen. Der index kann dabei eine normale Variable, ein String oder wiederum ein indiziertes Array sein.
foreach loop_var in var_n
do
statement
done
Diese Schleife laeuft von 1 bis var_n. Man kann die Schleifenvariable loop_var dazu benutzen, um _% Variablen zu indizieren. Will man also nicht nur über eine _% Variable iterieren, sondern über mehrere gleichzeitig, nimmt man diese Variante der Schleife und verwendet die loop_var zum Indizieren mehrerer _% Variablen.
Die Expressions erlauben so gut wie alles, was man von einer Programmiersprache gewöhnt ist. Ein in einem Ausdruck auftauchender Wert 'val' kann eine Variable, ein String oder ein indiziertes Array sein. Variablen in Strings werden dabei wie oben beschrieben ersetzt. Ein Test auf die Gleichheit zweier Variablen könnte also so aussehen:
var1 == var2
"$var1" == "$var"
Zu beachten ist dabei, dass der Vergleich in Abhängigkeit vom Typ der Variable erfolgt, der in /etc/check.d/$package festgelegt wurde. Variablen, die als Typnamen einen mit NUM beginnenden Namen haben, erhalten einen numerischen Typ. Ist einer der beiden Variablen numerisch, erfolgt der Vergleich auf numerischer Basis, d.h. die Zeichenketten werden in Zahlen umgewandelt und dann vergleichen. Sonst erfolgt der Vergleich auf String-Basis; ein Vergleich von '05' und '5' geht ergibt ungleich, ein Vergleich von '18' und '9' ergibt '18' < '9'.
Für den Vergleich von Versionen wird das Hilfskonstrukt numeric(version) eingeführt, welches den numerischen Wert für einen Versionsstring für Vergleichszwecke bestimmt . numeric(version) == sub_version + 1000 * minor_version + 10000 * major_version:
Eine vollständige Auflistung aller Ausdrücke ist in der folgenden Tabelle zu finden.
| expr | true if |
| id | id == 'yes' |
| val == val | strings/numerische Werte sind identisch |
| val != val | strings/numerische Werte sind verschieden |
| val == number | numerischer Wert von val == number |
| val != number | numerischer Wert von val != number |
| val < number | numerischer Wert von val < number |
| val > number | numerischer Wert von val > number |
| val == version | numeric(val) == numeric(version) |
| val < version | numeric(val) < numeric(version) |
| val > version | numeric(val) > numeric(version) |
| ( expr ) | Ausdruck in Klammern ist wahr |
| expr && expr | beide Ausdrücke sind wahr |
| expr || expr | mind. einer der beiden Audrücke ist wahr |
Um die Eingabe von Werten in der eisfair-Konfiguration noch einfacher und sicherer zu gestalten, sieht der Eisfair Konfigurationseditor (ECE) eine Möglichkeit vor, die einfache Eingabezeile zur Parameterbearbeitung gegen selbstdefinierte Dialoge zu tauschen. In solchen Dialogen können Werte z.B. als Auswahllisten oder in jeder anderen denkbaren Form dem Anwender verfügbar gemacht werden.
Damit der ECE einen Dialog verwendet müssen die folgenden Bedingungen erfüllt sein:
Zum einen muss in der Datei /etc/check.d/$package eine Prüfregel eingetragen werden, die der Variablen einen eindeutigen symbolischen Typnamen zuordnet. Kann das mit einer speziellen Typprüfung verbunden werden, dann steht ein solcher Name oftmals ohnehin zur Verfügung, anderenfalls muss eine ''leere'' Prüfregel definiert werden. Beispiel:
Beispiel für eine Datei /etc/check.d/$package für einen ECE-Dialog :
FOO_NETWORK - - IPADDR FOO_NETWORK - - FOO_IP FOO_DIR_N - - NUMERIC FOO_DIR_%_ACCESS - FOO_DIR_N FOO_ACCESS
In dem oben aufgeführten Beispiel wird angenommen, dass ein Paket FOO für die Konfigurationsvariable FOO_NETWORK einen speziellen Dialog zur Eingabe oder Auswahl einer IP-Adresse definieren möchte. Als Prüfregel kommt dabei die in der Basis definierte Regel IPADDR zum Einsatz, weshalb eine weitere Regel für die selbe Variable eingefügt wurde, die lediglich einen Bezeichner (FOO_IP) definiert (IPADDR wäre nicht eindeutig!).
Zudem kennt die Konfiguration des FOO-Pakets die Variable FOO_DIR_%_ACCESS, welche ebenfalls einen Dialog erhalten soll. Hier gibt es aber bereits die paketspezifische Prüfregel FOO_ACCESS, die eindeutig genug ist, um direkt als Bezeichner verwendet werden zu können.
Selbstverständlich müssen für FOO_IP und FOO_ACCESS ebenfalls Einträge in der Datei /etc/check.d/$package.exp angelegt werden.
Beispiel für eine Datei /etc/check.d/$package.exp für einen ECE-Dialog :
FOO_IP = '(RE:NONE)'
: ''
FOO_ACCESS = 'none|read|write'
: 'only none, read or write are allowed'
Zu guter letzt können nun im Verzeichnis /var/install/dialog.d shell-Skripte erstellt werden, die vom ECE verwendet werden sollen. Damit die Zuordnung zu den Variablen funktioniert sind die Namen der Skripte so zu wählen, dass sie den zuvor definierten Typbezeichnern entsprechen. Im Beispiel wären dies: FOO_IP.sh und FOO_ACCESS.sh (wobei die Gross- Kleinschreibung zu beachten ist!).
Die Skripte selbst können komplexe Programme enthalten und müssen dabei der CUI Skript-Spezifikation entsprechen. Die Syntax und das erforderliche Hintergrundwissen vermittelt das Dokument ''libcuidoc'', das ebenfalls auf der Webseite des eisfair-Projekts zu finden ist. Neben der C-API der libcui wird dort auch die Skript-Schnittstelle beschrieben und eine Referenz der verfügbaren Skript-Befehle geliefert.
An dieser Stelle sollen lediglich zwei Beispiele für Skripte vorgestellt werden, mit denen man Auswahllisten im ECE realisieren kann. Diese Skripte können kopiert und auf vergleichbare Fälle angepasst werden:
Der in der ecelib definierte Dialog ''ece_select_list_dlg'' implementiert eine einfache Auswahlliste, die zentriert über dem Editorfenster angezeigt wird. Der Anwender kann dabei aus einer Reihe möglicher Werte wählen und den gewünschten Wert (z.B. mit Enter) gestätigen. Die Auswahl wird dann in die bearbeitete Konfigurationsvariable des ECE übertragen.
Beispiel für die Verwendung des Dialogs ece_select_list_dialog :
#! /bin/bash
. /var/install/include/cuilib
. /var/install/include/ecelib
#-----------------------------------------------------------------
# exec_dailog
# ece --> request to create and execute dialog
# $p2 --> main window handle
# $p3 --> name of config variable
#-----------------------------------------------------------------
function exec_dialog()
{
local win="$p2"
sellist="BLACK,RED,GREEN,BROWN,BLUE,MAGENTA,CYAN,LIGHTGRAY,"
DARKGRAY,LIGHTRED,LIGHTGREEN,YELLOW,LIGHTBLUE,
LIGHTMAGENTA,LIGHTCYAN,WHITE"
ece_select_list_dlg "$win" "Colors" "$sellist"
}
#-----------------------------------------------------------------
# main routine
#-----------------------------------------------------------------
cui_init
cui_run
#-----------------------------------------------------------------
# end
#-----------------------------------------------------------------
exit 0
Der Dialog ''ece_comment_list_dlg'' ist eine Erweiterung des ''ece_select_list_dlg'' Dialogs. Hier ist es möglich neben den Auswahloptionen Kommentare anzugeben, die gemeinsam mit den Auswahlwerten in einer zweispaltigen Auswahlliste dargestellt werden. Auf diese Weise sieht der Anwender nicht nur die Optionen (die für sich gesehen u.U. vergleichsweise nichtssagend sind), sondern auch einen erklärenden Text, der die Auswahl erleichtert.
Beispiel für die Verwendung des Dialogs ece_comment_list_dialog :
#! /bin/sh
. /var/install/include/cuilib
. /var/install/include/ecelib
#-----------------------------------------------------------------
# exec_dailog
# ece --> request to create and execute dialog
# $p2 --> main window handle
# $p3 --> name of config variable
#-----------------------------------------------------------------
function exec_dialog()
{
local win="$p2"
sellist="option1|Dies ist Option1,option2|Dies ist Option2,
option3|Dies ist Option3,option4|Dies ist Option4"
ece_comment_list_dlg "$win" "Optionen" "$sellist"
}
#-----------------------------------------------------------------
# main routine
#-----------------------------------------------------------------
cui_init
cui_run
#-----------------------------------------------------------------
# end
#-----------------------------------------------------------------
exit 0
Yves Schumann 2012-02-05