Subsections

8.7 Hochfahren, Herunterfahren, Einwählen und Auflegen unter fli4l

8.7.1 Bootkonzept

fli4l 2.0 sollte eine saubere Installation auf eine Festplatte oder ein CompactFlash(TM)-Medium bieten, aber auch eine Installation auf ein Zip-Medium oder die Erstellung einer bootfähigen CD-ROM sollte möglich sein. Zusätzlich sollte die Festplattenversion sich nicht grundlegend von einer Installation auf Diskette8.10 unterscheiden.

Diese Anforderungen wurden realisiert, indem die Dateien des opt.img-Archivs aus der bisherigen RAM-Disk auf eine anderes Medium verlagert werden können. Dies kann eine Partition auf einer Festplatte bzw. einem CF-Medium sein. Dieses zweite Volume wird unter /opt eingehängt, und dort liegende Programme werden nur noch über symbolische Links in das RootFS integriert. Das entstehende Layout im RootFS-Dateisystem entspricht dann dem im opt-Verzeichnis der ausgepackten fli4l-Distribution mit einer Ausnahme - das files-Präfix entfällt. Die Datei opt/etc/rc ist dann also direkt unter /etc/rc zu finden, opt/files/bin/busybox unter /bin/busybox. Dass diese Dateien unter Umständen nur symbolische Verknüpfungen auf ein im Nur-Lese-Modus eingehängtes Volume sind, kann man ignorieren, solange man die Dateien nicht modifizieren möchte. Will man dies tun, muss man die Dateien vorher mit mk_writable (s.u.) schreibbar machen.

8.7.2 Start- und Stopp-Skripte

Skripte, die beim Hochfahren des Systems ausgeführt werden sollen, befinden sich in den Verzeichnissen opt/etc/boot.d/ und opt/etc/rc.d/ und werden auch in dieser Reihenfolge ausgeführt. Des Weiteren befinden sich in opt/etc/rc0.d/ Skripte, die beim Herunterfahren des Systems ausgefühlt werden.


Wichtig: Da zum Ausführen dieser Skripte kein separater Prozess erzeugt wird, dürfen sie nicht mit "`exit"' abgeschlossen werden. Ein solcher Befehl führt zum vorzeitigen Abbruch des Bootvorgangs!

8.7.2.1 Start-Skripte in opt/etc/boot.d/

Skripte, die in diesem Verzeichnis liegen, werden als erstes ausgeführt. Ihre Aufgabe ist es, das Boot-Volume einzuhängen, die auf dem Boot-Medium liegende Konfigurationsdatei rc.cfg einzulesen und das Opt-Archiv zu entpacken. Je nach Boot-Typ sind diese Skripte mehr oder weniger kompliziert und tun die folgenden Dinge:

Damit die Skripte überhaupt eine Chance haben, etwas über die fli4l-Konfiguration zu erfahren, wird die Konfigurationsdatei auch ins RootFS-Archiv unter /etc/rc.cfg eingebunden; die Konfigurationsvariablen in dieser Datei stehen den Start-Skripten in opt/etc/boot.d/ direkt zur Verfügung. Nach dem Einhängen des Boot-Volumes wird die /etc/rc.cfg durch die Konfigurationsdatei vom Boot-Volume ersetzt, so dass den Start-Skripten in opt/etc/rc.d/ (s.u.) die aktuelle Konfiguration vom Boot-Volume zur Verfügung steht. 8.11

8.7.2.2 Start-Skripte in opt/etc/rc.d/

Befehle, die immer beim Starten des Routers ausgeführt werden müssen, können in Skripten im Verzeichnis opt/etc/rc.d/ abgelegt werden. Hierbei gelten folgende Konventionen:

  1. Es gilt folgende Namenskonvention:

        rc<dreistellige Zahl>.<Name des OPTs>
    

    Die Skripte werden in aufsteigender Reihenfolge der Zahlen gestartet. Ist mehreren Skripten dieselbe Zahl zugeordnet, entscheidet die alphabetische Sortierung nach dem Punkt. Falls der Start eines Pakets erst nach einem anderen erfolgen darf, wird das durch die Zahl festgelegt.

    Hier eine ungefähre Richtlinie, welche Nummern für welche Aufgaben verwendet werden sollten:


    Nummer Aufgabe
    000-099 Grundsystem (Hardware, Zeitzone, Dateisystem)
    100-199 Kernel-Module (Treiber)
    200-299 externe Verbindungen (PPPoE, ISDN4Linux, PPtP)
    300-399 Netzwerk (Routing, Interfaces, Paketfilter)
    400-499 Server (DHCP, HTTPD, Proxy, etc.)
    500-900 beliebig
    900-997 Alles, was eine Einwahl hervorrufen könnte
    998-999 reserviert (bitte nicht benutzen!)

  2. In diesen Skripten müssen alle Funktionen, die das RootFS verändern, hinterlegt werden, etwa das Anlegen eines Verzeichnisses /var/log/lpd.

  3. In diesen Skripten dürfen keine Schreibzugriffe auf Dateien erfolgen, die Teil des Opt-Archivs sein können, da diese Dateien auf einem im Nur-Lese-Modus eingehängten Volume liegen können. Muss man eine solche Datei modifizieren, muss man sie vorher mit Hilfe der Funktion mk_writable (s.u.) beschreibbar machen. Durch den Aufruf der Funktion wird die Datei (wenn nötig) als beschreibbare Kopie im RootFS abgelegt. Ist die Datei bereits beschreibbar, bewirkt der mk_writable-Aufruf nichts.


    Wichtig: mk_writable muss direkt auf Dateien im RootFS angewandt werden, nicht über den Umweg des opt-Verzeichnisses. Will man also /usr/local/bin/foo modifizieren, ruft man mk_writable mit dem Argument /usr/local/bin/foo auf.

  4. Diese Skripte müssen vor der Ausführung der eigentlichen Befehle prüfen, ob das dazugehörige OPT auch aktiv ist. Das ist normalerweise durch eine einfache Fallunterscheidung erledigt:

        if [ "$OPT_<OPT-Name>" = "yes" ]
        then
            ...
            # Hier OPT starten!
            ...
        fi
    

  5. Um die Fehlersuche zu erleichtern, sollten die Skripte mit begin_script und end_script geklammert werden:

        if [ "$OPT_<OPT-Name>" = "yes" ]
        then
            begin_script FOO "configuring foo ..."
            ...
            end_script
        fi
    

    Die Fehlersuche einzelner Start-Skripte kann man dann einfach via FOO_DO_DEBUG='yes' aktivieren.

  6. Den Skripten stehen alle Konfigurationsvariablen direkt zur Verfügung. Im Abschnitt "`Umgang mit Konfigurationsvariablen"' wird erklärt, wie man von anderen Skripten aus auf die Konfigurationsvariablen zugreifen kann.

  7. Der Pfad /opt darf auch nicht als Speicherplatz für Datenbestände der OPTs benutzt werden. Falls zusätzlicher Speicherplatz benötigt wird, sollte dem Benutzer über eine Konfigurationsvariable die Möglichkeit gegeben werden, einen geeigneten Pfad auszuwählen. Je nach Art der zu speichernden Daten (persistente oder transiente Daten) sind verschiedene Standard-Belegungen sinnvoll. So bieten sich für transiente Daten etwa Pfade unterhalb von /var/run/ an; für persistente Daten sollte die Funktion map2persistent in Kombination mit einer geeigneten Konfigurationsvariable verwendet werden.

8.7.2.3 Stopp-Skripte in opt/etc/rc0.d/

Jeder Rechner muss mal heruntergefahren oder neu gestartet werden. Nun kann es vorkommen, dass man Vorgänge ausführen muss, bevor der Rechner heruntergefahren oder neu gestartet wird. Zum Herunterfahren und Neustarten sind die Befehle "`halt"' bzw. "`reboot"' zuständig. Diese Befehle werden auch aufgerufen, wenn man im IMONC oder in der Web-GUI auf die entsprechenden Schaltflächen klickt.

Alle Stopp-Skripte liegen im Verzeichnis opt/etc/rc0.d/. Ihre Dateinamen werden analog zu den Start-Skripten gebildet. Sie werden ebenfalls in aufsteigender Reihenfolge der Zahlen ausgeführt.

8.7.3 Hilfsfunktionen

In /etc/boot.d/base-helper werden verschiedene Funktionen bereitgestellt, die von den Start- und anderen Skripten verwendet werden können. Das betrifft Dinge wie Unterstützung zur Fehlersuche, Laden von Kernel-Modulen oder Ausgabe von Meldungen. Die einzelnen Funktionen werden im Folgenden aufgelistet und kurz beschrieben.

8.7.3.1 Skript-Steuerung

begin_script <Symbol> <Meldung>:
Gibt eine Meldung aus und aktiviert die Fehlersuche im Skript mittels set -x, falls <Symbol>_DO_DEBUG auf "`yes"' steht.

end_script:
Gibt eine Abschluss-Meldung aus und deaktiviert die Fehlersuche, falls sie mit begin_script aktiviert wurde. Für jeden begin_script-Aufruf muss es einen zugehörigen end_script-Aufruf geben (und umgekehrt).

8.7.3.2 Laden von Kernel-Modulen

do_modprobe [-q] <Modul> <Parameter>*:
Lädt ein Kernel-Modul inkl. eventueller Parameter bei gleichzeitiger Auflösung der Modulabhängigkeiten. Der Parameter "`-q"' verhindert, dass im Fehlerfall eine Meldung auf der Konsole ausgegeben und ins Boot-Protokoll geschrieben wird. Die Funktion liefert im Erfolgsfall den Rückgabewert null zurück und im Fehlerfall einen Wert ungleich null. Damit lässt sich Code schreiben, der ein Fehlschlagen des Ladens eines Kernel-Moduls geeignet behandelt:

    if do_modprobe -q acpi-cpufreq
    then
        # kein CPU-Frequenzsteuerung via ACPI
        log_error "CPU-Frequenzsteuerung via ACPI nicht verfügbar!"
        # [...]
    else
        log_info "CPU-Frequenzsteuerung via ACPI aktiviert."
        # [...]
    fi

do_modrobe_if_exists [-q] <Modulpfad> <Modul> <Parameter>*:

Prüft, ob das Modul /lib/modules/<Kernel-Version>/<Modulpfad>/<Modul> existiert und ruft bei Vorhandensein die Funktion do_modprobe auf.


Wichtig: Das Modul muss tatsächlich unter dem angegebenen Modulnamen existieren, der Modulname darf kein Alias sein. Bei einem Alias wird direkt do_modprobe aufgerufen.

8.7.3.3 Meldungen und Fehlerbehandlung

log_info <Meldung>:
Schreibt eine Meldung auf die Konsole und nach /bootmsg.txt. Wird keine Meldung als Parameter übergeben, liest log_info von der Standard-Eingabe. Die Funktion liefert als Rückgabewert immer null zurück.

log_warn <Meldung>:
Schreibt eine Warnmeldung auf die Konsole und nach /bootmsg.txt, wobei vor die Meldung die Zeichenkette WARN: gesetzt wird. Wird keine Meldung als Parameter übergeben, liest log_warn von der Standard-Eingabe. Die Funktion liefert als Rückgabewert immer null zurück.

log_error <Meldung>:
Schreibt eine Fehlermeldung auf die Konsole und nach /bootmsg.txt, wobei vor die Meldung die Zeichenkette ERR: gesetzt wird. Wird keine Meldung als Parameter übergeben, liest log_error von der Standard-Eingabe. Die Funktion liefert als Rückgabewert immer einen Wert ungleich null zurück.

set_error <Meldung>:
Gibt die Fehlermeldung aus und setzt eine interne Fehlervariable, das später via is_error geprüft werden kann.

is_error:
Setzt die interne Fehlervariable zurück und liefert wahr zurück, falls sie vorher durch set_error gesetzt wurde.

8.7.3.4 Netzwerk-Funktionen

translate_ip_net <Wert> <Variablenname> [<Ergebnisvariable>]:
Ersetzt symbolische Referenzen in Parametern. Momentan finden folgende Übersetzungen statt:
*.*.*.*, none, default, pppoe
werden nicht übersetzt
any
wird durch 0.0.0.0/0 ersetzt
dynamic
wird durch die IP-Adresse des Routers ersetzt, über welche die Verbindung zum Internet besteht
IP_NET_x
wird durch das in der Konfiguration stehende Netzwerk ersetzt
IP_NET_x_IPADDR
wird durch die in der Konfiguration stehende IP-Adresse ersetzt
IP_ROUTE_x
wird durch das in der Konfiguration stehende geroutete Netzwerk ersetzt
@<Hostname>
wird durch die in der Konfiguration für den angegeben Host spezifizierte IP-Adresse ersetzt

Das Ergebnis der Übersetzung wird in der Variable gespeichert, deren Name im dritten Parameter übergeben wird; fehlt dieser Parameter, wird das Ergebnis in der Variable res gespeichert. Der Variablenname, der im zweiten Parameter übergeben wird, wird nur für Fehlermeldungen benutzt, falls die Übersetzung fehlschlägt; hier kann also vom Aufrufer die Quelle des zu übersetzenden Wertes angegeben werden. Im Fehlerfall wird dann eine Meldung wie

    Unable to translate value '<Wert>' contained in <Variablenname>.

ausgegeben.

Der Rückgabewert ist null, falls die Übersetzung erfolgreich war, und ungleich null, falls ein Fehler aufgetreten ist.

8.7.3.5 Diverses

mk_writable <Datei>:
Stellt sicher, dass die übergebene Datei beschreibbar ist. Befindet sich die Datei auf einem im Nur-Lese-Modus eingehängten Volume und ist lediglich über eine symbolische Verknüpfung ins Dateisystem eingebunden, wird eine lokale Kopie angelegt, die dann beschreibbar ist.

unique <Liste>:
Entfernt Duplikate aus der übergebenen Liste. Das Resultat wird in der Variable list zurückgegeben.

8.7.4 ttyI-Geräte

Für die ttyI-Geräte (/dev/ttyI0 .../dev/ttyI15), über welche die "`Modem-Emulation"' der ISDN-Karte genutzt werden kann, existiert ein Zähler, um Konflikte zwischen verschiedenen Paketen, die diese Geräte nutzen, zu vermeiden. Hierzu wird beim Start des Routers die Datei /var/run/next_ttyI angelegt, die von den verschiedenen OPTs abgefragt und fortgezählt werden kann. Mit dem folgenden Beispielskript kann dieser Wert abgefragt, um eins erhöht und wieder für das nächste OPT exportiert werden.

    ttydev_error=
    ttydev=$(cat /var/run/next_ttyI)
    if [ $ttydev -le 16 ]
    then                                    # ttyI device available? yes
        ttydev=$((ttydev + 1))              # ttyI device + 1
        echo $ttydev >/var/run/next_ttyI    # save it
    else                                    # ttyI device available? no
        log_error "No ttyI device for <Name deines OPTs> available!"
        ttydev_error=true                   # set error for later use
    fi

    if [ -z "$ttydev_error" ]               # start OPT only if next tty device
    then                                    # was available to minimize error
        ...                                 # messages and minimize the
                                            # risk of uncomplete boot
    fi

8.7.5 Skripte beim Einwählen und Auflegen

8.7.5.1 Allgemeines

Nach dem Herstellen bzw. Trennen einer Wählverbindung werden die Skripte in /etc/ppp/ abgearbeitet. Hier können OPTs Aktionen hinterlegen, die nach dem Herstellen bzw. Auflegen der Verbindung nötig sind. Benannt werden die Dateien wie folgt:


ip-up<dreistellige Zahl>.<OPT-Name>
ip-down<dreistellige Zahl>.<OPT-Name>

Dabei werden die ip-up-Skripte nach dem Aufbau und die ip-down-Skripte nach dem Abbau der Verbindung ausgeführt.


Wichtig: In den ip-down-Skripten dürfen keine Aktionen ausgeführt werden, die zu einer erneuten Einwahl führen, da dadurch nur ein Dauer-Online-Zustand erreicht wird, was für Nicht-Flatrate-Benutzer ein teures Unterfangen ist.


Wichtig: Da für die einzelnen Skripte kein eigener Prozess erzeugt wird, dürfen auch diese Skripte nicht mit "`exit"' abgeschlossen werden!

Hinweis: Wenn ein Skript prüfen will, ob überhaupt die ip-up-Skripte ausgeführt werden, kann es ab rc400 die Variable ip_up_events prüfen. Steht diese auf "`yes"', gibt es Wählverbindungen, und die ip-up-Skripte werden ausgeführt. Steht diese auf "`no"', sind keine Wählverbindungen konfiguriert, und es werden keine ip-up-Skripte ausgeführt. Von dieser Regel gibt es eine Ausnahme: Wenn ein reiner Ethernet-Router ohne Wählverbindungen konfiguriert wurde, aber eine Default-Route (0.0.0.0/0) existiert, so werden am Ende des Boot-Vorgangs die ip-up-Skripte genau einmal ausgeführt. (Analog werden vor dem Herunterfahren einmalig die ip-down-Skripte ausgeführt.)

8.7.5.2 Variablen

Durch das spezielle Aufrufkonzept stehen die folgenden Variablen den ip-up- und ip-down-Skripten zur Verfügung:


real_interface die aktuelle Schnittstelle, also z.B. ppp0, ippp0, ...
interface das IMOND-Interface, also pppoe, ippp0, ...
tty verbundenes Terminal, möglicherweise leer!
speed die Verbindunggeschwindigkeit, bei ISDN z.B. 64000
local die eigene IP-Adresse
remote die IP-Adresse des Point-To-Point-Partners
is_default_route gibt an, ob das aktuelle ip-up/ip-down für die Schnittstelle durchgeführt wird, über welche die Default-Route geht (kann "`yes"' oder "`no"' sein)

8.7.5.3 Default-Route

Seit Version 2.1.0 werden die ip-up/ip-down-Skripte nicht nur für die Schnittstelle ausgeführt, über welche die Default-Route geht, sondern für alle Verbindungen, welche die ip-up- und ip-down-Skripte aufrufen. Um das alte Verhalten zu simulieren, muss in ip-up- und ip-down-Skripten die folgende Abfrage eingefügt werden:

    # is a default-route-interface going up?
    if [ "$is_default_route" = "yes" ]
    then
        # die eigentlichen Aktionen
    fi

Natürlich darf das neue Verhalten auch für spezielle Aktionen ausgenutzt werden.



Footnotes

... Diskette8.10
Ursprünglich konnte fli4l auch von einer Diskette betrieben werden. Da fli4l inzwischen dafür zu groß geworden ist, wird dies nicht mehr unterstützt.
... steht.8.11
Normalerweise sind diese beiden Dateien identisch. Eine Abweichung entsteht nur, wenn die Konfigurationsdatei auf dem Boot-Volume händisch editiert wird, etwa um die Konfiguration nachträglich abzuändern, ohne die fli4l-Archive neu zu bauen.
© 2001-2019 Das fli4l-Team - April 28, 2019