Hier folgt jetzt keine allgemeine Einführung in Shell-Skripte, das kann jeder im Internet selber nachlesen, es wird nur auf die spezielle Gegebenheiten bei fli4l eingegangen. Informationen dazu gibt es in den diversen Unix-/Linux-Hilfeseiten. Folgende Links können als Einstiegspunkte zu diesem Thema dienen:
In der Unix-Welt ist es nötig, ein Skript mit dem Namen des Interpreters zu beginnen, daher steht in der ersten Zeile:
#!/bin/sh
Damit man später leichter erkennen kann, was ein Skript macht und wer es geschrieben hat, sollte jetzt ein kurzer Header folgen, in etwa so:
#-------------------------------------------------------------------- # /etc/rc.d/rc500.dummy - start my cool dummy server # # Creation: 19.07.2001 Toller Hecht <toller-hecht@example.net> # Last Update: 11.11.2001 Süße Maus <suesse-maus@example.net> #--------------------------------------------------------------------
Nun kann das eigentliche Skript folgen...
Pakete werden über die Datei config/<PACKAGE>.txt konfiguriert. Die darin enthaltenen und aktiven Variablen werden beim Erzeugen des Boot-Mediums in die Datei rc.cfg übernommen. Beim Booten des Routers wird diese Datei eingelesen, bevor irgend ein rc-Skript (Skripte unter /etc/rc.d/) gestartet wird. Diese Skripte können dadurch auf alle Konfigurationsvariablen einfach durch $<Variablenname> zugreifen.
Benötigt man Werte von Konfigurationsvariablen auch noch nach dem Booten, dann kann man sie aus der /etc/rc.cfg extrahieren, in welche während des Bootens die Konfiguration des Boot-Mediums geschrieben wurde. Möchte man beispielsweise den Wert der Variable OPT_DNS in einem Skript auslesen, so kann man dies folgendermaßen tun:
eval $(grep "^OPT_DNS=" /etc/rc.cfg)
Das funktioniert auch mit mehreren Variablen effizient (d.h. mit nur einem Aufruf des grep-Programms):
eval $(grep "^\(HOSTNAME\|DOMAIN_NAME\|OPT_DNS\|DNS_LISTEN_N\)=" /etc/rc.cfg)
Gelegentlich benötigt ein Paket die Möglichkeit, Daten persistent abzulegen, die also einen Neustart des Routers überleben. Dazu existiert die Funktion map2persistent, die von einem Skript in /etc/rc.d/ aufgerufen werden kann. Sie erwartet eine Variable, die einen Pfad enthält, und ein Unterverzeichnis. Die Idee ist, dass die Variable entweder einen tatsächlichen Pfad beschreibt - dann wird dieser Pfad auch genommen, denn der Nutzer hat ihn so gewünscht, oder die Zeichenkette "`auto"' - dann wird unterhalb eines Verzeichnisses auf einem persistenten Medium ein entsprechendes Unterverzeichnis gemäß dem zweiten Parameter erzeugt. Die Funktion liefert das Resultat in eben der Variable zurück, deren Name im ersten Parameter übergeben wurde.
Ein Beispiel soll dies verdeutlichen. Sei VBOX_SPOOLPATH eine Variable, die einen Pfad oder die Zeichenkette "`auto"' enthält. Dann führt der Aufruf
begin_script VBOX "Configuring vbox ..." [...] map2persistent VBOX_SPOOLPATH /spool [...] end_script
dazu, dass die Variable VBOX_SPOOLPATH entweder gar nicht verändert wird (falls sie einen Pfad enthält), oder dass sie durch den Pfad /var/lib/persistent/vbox/spool ersetzt wird (falls sie die Zeichenkette "`auto"' enthält). Dabei verweist8.6 /var/lib/persistent auf ein Verzeichnis auf einem beschreibbaren und nicht flüchtigen Speichermedium, und <SCRIPT> stellt das aufrufende Skript in Kleinbuchstaben dar (dieser Name wird vom ersten Argument des begin_script-Aufrufs abgeleitet). Falls kein geeignetes Medium existieren sollte (was durchaus sein kann), ist /var/lib/persistent ein Verzeichnis in der RAM-Disk.
Zu beachten ist, dass der Pfad, der von map2persistent zurückgegeben wird, nicht automatisch erzeugt wird - das muss der Aufrufer selbst erledigen (etwa durch einen Aufruf von mkdir -p <Pfad>).
In der Datei /var/run/persistent.conf kann nachgeschaut werden, ob die persistente Speicherung von Daten möglich ist. Beispiel:
. /var/run/persistent.conf case $SAVETYPE in persistent) echo "Persistente Speicherung möglich!" ;; transient) echo "Persistente Speicherung NICHT möglich!" ;; esac
Bei Start-Skripten ist es oft sinnvoll, diese bei Bedarf im Debug-Modus der Shell laufen zu lassen, um festzustellen, wo "`der Wurm drin ist"'. Dazu wird am Anfang und am Ende folgendes eingefügt:
begin_script <OPT-Name> "start message" <script code> end_script
Im normalen Betrieb erscheint jetzt beim Start des Skriptes der angegebene Text und am Ende der gleiche Text mit einem vorangestellten "`finished"'.
Will man die Skripte debuggen, muss man zwei Dinge tun:
<OPT-Name>_DO_DEBUG='yes'in der Konfigurationsdatei.8.7 Jetzt wird während der Ausführung am Bildschirm genau dargestellt, was passiert.
Diese Variable gestattet das Erzeugen von "`Core-Dumps"' (Speicherauszügen). Stürzt ein Programm aufgrund eines Fehlers ab, wird ein Abbild des aktuellen Zustandes im Dateisystem abgelegt, der hinterher zur Analyse des Problems verwendet werden kann. Die Core-Dumps werden unter /var/log/dumps/ abgelegt.
Wird diese Variable gesetzt, werden alle Aufrufe des Programms ip protokolliert.
Wird diese Variable auf "`yes"' gesetzt, werden während der Ausführung der ip-up/ip-down-Skripte die ausgeführten Anweisungen mitgezeichnet und im System-Protokoll gespeichert.
Wird diese Variable auf "`yes"' gesetzt, protokolliert der bootlogd während des Bootens alle auf der Konsole getätigten Ausgaben in der Datei /var/tmp/boot.log. Diese Variable hat standardmäßig den Wert "`yes"'.
Normalerweise wird der bootlogd am Ende des Bootvorganges beendet. Ein Setzen dieser Variable unterbindet das und erlaubt ein Protokollieren der Konsolenausgaben über den Bootvorgang hinaus.
Ein Setzen dieser Variable generiert ein Protokoll des mdev-Daemons, der für das Anlegen der Geräte-Dateien unter /dev zuständig ist.
{ echo "cpu"; echo "quit"; } | ...
gleichbedeutend mit:
{ echo "cpu" echo "quit" } | ...