Home   Artikel   Archiv   Forum   Impressum  
Artikel vom 27.3.2002
Autor: Günther Zander
Languages: en
Artikel bewerten:

Printer Druckversion
Helfen Sie mit!
 

Eigene Initscripte erstellen bei SuSE 7.x


Der größte Vorteil von einem Linuxsystem ist, dass dieses System den individuellen Bedürfnissen angepasst werden kann. Mit diesem Beitrag werden Sie in die Lage versetzt, Ihr System während der Initialisierungsphase nach Ihren Bedürfnissen zu starten. Neben einer notwendigen Einführung, werden Ihnen die benötigten Programme, Scripte und deren Abhängigkeiten erklärt.
Dieses wird am Beispiel der Verteilung der amtlichen Atomzeit im Intranet bei einer sporadischen Modemverbindung zum Internet dargestellt.

Ein bischen Theorie muss sein

Das SuSE-Initkonzept lässt sich grob in vier Teilbereiche zusammenfassen. Diese sind das Init-Programm, die Runlevels, die Init-Scripte mit deren Konfigurationsdateien so wie das Linksystem.

Das Init-Programm

Nach dem Starten des Rechners und der Meldung "Uncompressing Linux .... " übernimmt der Kernel die Kontrolle über die gesamte Hardware des Systems. Nachdem die vorhandene Hardware vorinitialisiert wurde, mountet der Kernel das Root-Dateisystem und startet das Programm "init". Dieses Programm ist für die korrekte Initialisierung des Systems zuständig.

Dieses Programm nimmt eine Sonderrolle ein, da es direkt vom Kernel, als einziges, gestartet wird, und sich nicht unterbrechen lässt. Es ist immun gegen das Kill-Signal 9. Alle weiteren Programme werden von diesem Programm gestartet! Konfiguriert wird das Programm über die Datei /etc/inittab. In dieser Datei sind unter anderem die Runlevels definiert. Das gesamte Hochlaufen des Systems, wie auch das Herrunterfahren, wird somit einzig und allein vom Init-Prozess gesteuert.

Die Runlevels

Die Runlevels wurden eingeführt, um ein Linux-System besser an die benötigten Gegebenheiten anpassen zu können. Es existieren verschiedene Runlevels, die den jeweiligen Zustand des Systems definieren. Der Runlevel, mit dem das System defaultmäßig gestartet wird, steht in der Datei /etc/inittab und wird durch den Eintrag, hier für Runlevel 5, "id:5:initdefault:" festgelegt.

Alternativ kann der gewünschte Runlevel beim Booten des Systems angegeben werden, sobald die Meldung "boot :" erscheint, indem Sie "init X" eingeben. Falls Sie mit dem LILO Bootmanager arbeiten sollten, müssen Sie noch ihre Auswahl aus dem LILO voranstellen. Z.B. "boot : linux24 init 3"

  	Liste der gültigen Runlevels unter Linux
  
  	0	System anhalten (halt)
  	S	Einzelbenutzerbetrieb mit US-Tastaturbelegung
  	1	Einzelbenutzerbetrieb mit lokaler Tastaturbelegung
  	2	Mehrbenutzerbetrieb ohne Netzwerk
  	3	Mehrbenutzerbetrieb mit Netzwerk
  	5	Mehrbenutzerbetrieb mit Netzwerk und grafischer Oberfläche
  	6	Systemneustart (reboot)
  

Wenn Sie als root angemeldet sind, können Sie die Runlevels mit "init X" nach Belieben wechseln. Bei einem Wechsel der Runlevels werden erst alle Stopp-Scripte des aktuellen Runlevels ausgeführt, und anschließend alle Start-Scripte, von dem Runlevel in den Sie wechseln wollen, ausgeführt.

Die Init-Scripte

Der Ort, wo die Init-Scripte hinterlegt sind, findet sich auch in der Datei /etc/inittab. Für den Runlevel 5 wäre das der Eintrag

  l5:5:wait:/etc/init.d/rc 5
  
Damit liegen die Scripte für diesen Runlevel im Verzeichnis /etc/init.d/rc5.d Das Kürzel rc steht übrigens für Resource Control (Systemkontrolle).

In dem Verzeichnis /etc/init.d sind nun alle Scripte untergebracht, die notwendig sind, um das System kontrolliert hoch- bzw. herrunterzufahren. Für jeden Runlevel existiert ein weiteres Unterverzeichnis rc[S,0-6].d. In diesen Verzeichnissen werden jedoch nur symbolische Links erstellt, die auf die entsprechenden Scripte im Verzeichniss /etc/init.d verweisen. Auf diese Weise wird verhindert, dass ein Script, das in mehreren Runlevels benötigt wird, mehrfach existiert, was den Wartungsaufwand eines Systems verringert.

Die symbolischen Links unterliegen einer Namenskonvention. An erster Stelle ist ein großer Buchstabe S oder K. Damit wird ausgedrückt, ob es sich um ein Startscript (S = Start) oder um ein Stoppscript (K = Kill) handelt. Es folgen immer zwei Zahlen 00 bis 99. Damit ist die Reihenfolge bestimmt, an welcher Stelle dieses Script abgearbeitet wird. Zum Schluss wird noch der Name für das Script in /etc/init.d angefügt. {K,S}[0-9][0-9]*

Hier eine Kurzbeschreibung der Scripte im Verzeichniss /etc/init.d, die eine Sonderstellung einnehmen:

boot Das Script boot wird bei einem Systemstart genau einmal ausgeführt, da dieses direkt vom Init-Prozess gestartet wird. Die dazu gehörenden Scripte liegen unter /etc/init.d/boot.d. Damit sind diese Scripte unabhängig von den Runlevels, und es beginnen alle Scripte mit 'S'. Als Beispielanwendung sei hier das Löschen von temporären Dateien angeführt.
boot.local In diesem Script können Sie alles eintragen, was das System beim Starten ausführen soll, bevor in einen Runlevel gewechselt werden soll. Dieses Script steht nur beim Systemstart, wie auch boot, zur Verfügung.
boot.setup Einstellungen für einen Wechsel von init S oder 1 in einen anderen Runlevel.
halt Bei Runlevel 0 oder 6 wird dieses Script aufgerufen, und je nach übergebenen Parameter, wird das System herruntergefahren oder neu gestartet (halt / reboot).
halt.local In diesem Script können Sie alles eintragen, was bei einem halt-Signal noch ausgeführt werden soll, bevor das Script den Befehl "halt" ausgeführt.
rc Erwähnenswert ist noch dieses Script, da es die Steuerung bei dem Übergang in andere Runlevels übernimmt. Hier werden die entsprechenden Start- und Stopp-Scripte aufgerufen, die für den entsprechenden Runlevel benötigt werden. Diese Datei bitte nicht editieren!
/etc/rc.config

Diese Datei enthält die Umgebungsvariablen, die von den einzelnen Scripten benötigt werden, um das System zu konfigurieren. Damit wird erreicht, dass Sie nur eine Datei für die unterschiedlichsten Bedürfnisse benötigen. Damit diese Datei nicht unendlich groß und damit unübersichtlich wird, werden einzelne Konfigurationsdateien in das Verzeichnis /etc/rc.config.d hinterlegt, wie die Datei firewall.rc.config.

Unter dem Punkt 'Konfigurationsdatei verändern' mittels Yast, werden alle Dateien im Verzeichnis /etc/rc.config.d eingelesen, sowie die Datei /etc/rc.config, bevor die Variableninhalte angezeigt werden. Die Dateien im Verzeichnis /etc/rc.config.d müssen folgenden Namensaufbau besitzen {Name der Datei}.rc.config .

Aufbau der Dateien /etc/rc.config und /etc/rc.config.d/*.rc.config

Durch das Kommentarzeichen '#' kann ein freier Text eingegeben werden, der die Möglichkeiten der nachfolgenden Variablen erklärt. Der gesamte Text hinter den Kommentarzeilen wird in Yast als Beschreibungstext angezeigt. In einer weiteren Zeile folgt der Name der Variablen und evtl. eine Vorbelegung {Name der Variablen}="". Zum Abschluss muss noch eine Leerzeile angehängt werden.

Das Linksystem

Alle Scripte, die für die Systemkontrolle benötigt werden, stehen im Verzeichniss /etc/init.d. In den Unterverzeichnissen rc[S,0-6].d sind Verweise auf die Scripte im Verzeichnis /etc/init.d vorhanden. Da diese Verzeichnisse nicht über die PFAD-Variable nach dem Einloggen zur Verfügung stehen, sind unter den Verzeichnissen /sbin und /usr/sbin, Links vorhanden, die auf diese Scripte verweisen. Diesen Links wird vor dem Scriptnamen ein "rc" vorrangestellt.

Die Scripts

Das Script, das einen Dienst bearbeitet, sollte mindestens die Optionen Start und Stop auswerten können, da diese Parameter beim Hoch- bzw. Herrunterfahren des Systems übergeben werden . Insgesamt können folgende Optionen eingebaut werden, wenn Sie ihr Script über rc{Scriptname} steuern wollen.

  	start           Dienst starten
  	stop            Dienst beenden
  	restart         Dienst erst beenden und anschließend wieder starten, 
  	                wenn der Dienst bereits lief. Ansonsten wird der Dienst 
  	                nur gestartet.
  	try-restart     Es wird nur ein Restart des Dienstes ausgeführt, aber 
  	                nur, wenn dieser bereits lief 
  	reload          Die Konfiguration eines Dienstes neu einlesen, ohne den 
  	                Dienst zu beenden oder zu starten.
  	force-reload    Konfiguration des Dienstes neu einlesen, wenn der Dienst 
  	                dieses zulässt, sonst vorgehen, wie unter restart.
  	status          Anzeige des aktuellen Status
  

Ein Beispielscript befindet sich unter /etc/init.d/skeleton. Die in diesem Script vorhandenen Teile BEGIN INIT INFO bis END INIT INFO werden von dem Program "insserv" ausgewertet. In diesem Script müssen Sie den Namen FOO gegen Ihren eigenem Namen austauschen und deren Parameter Ihren Bedürfnissen anpassen. Die Variable START_FOO wird nur ausgewertet, wenn Sie diesen Wert in der Datei /etc/rc.config auch erstellt haben.

SuSE Linux stellt ein weiteres Script bereit, /etc/rc.status, das die Optik beim Wechsel der Runlevels verbessert. Die Ausgabe der Variablen rc_status können Sie dabei selbst mit folgenden Optionen selbst bestimmen.

    Parameter		Bedeutung			Farbe	   Ausgabetext
  
    rc_status		OK				grün	   done		
    rc_status -v 		OK				grün	   done		
    rc_status -u		nichtvorhanden			weiß	   unused     	
    rc_status -s		überspringen			gelb	   skipped   	
    rc_status -r		löscht den aktuellen Status
    rc_failed		FEHLER				rot	   failed
    rc_reset		löscht den aktuellen Status
    rc_check 		Überprüfung des Status
    rc_exit		Beendet angemessen
        			den gesamten Status 
  

rc_status -v | -v[1-9] | -v[1-9][0-9]

Diese Variable kann noch mit einer max. 2-stelligen Zahl versehen werden. Diese Zahl gibt an, wie viele Zeilen der Cursor auf dem Bildschirm nach oben gehen soll, bevor der Inhalt der Variablen auf dem Bildschirm geschrieben wird.

Alle Services, die den Status 'failed' hatten, werden am Ende der Initialisierungsphase noch einmal in rot aufgeführt.

Das Programm insserv

Für das Anlegen und Entfernen der runlevelspezifischen Links ist das Programm "/sbin/insserv" gedacht. Dieses wertet dazu seine Datei /etc/insserv.conf aus, um die Links entsprechend den Abhängigkeiten zu erstellen. Diese Steuerung geschieht im Script zwischen den Einträgen BEGINN INIT INFO und END INIT INFO.

SuSE Linux wertet aber nur die Zeilen Required-Start und Default-Start aus. Damit wird nur ein Startlink erstellt, aber keinerlei Stopplinks. Es werden auch keine Links rc{Scriptname} in den Verzeichnissen /sbin oder /usr/sbin erstellt. SuSE verweist in der Dokumentation selbst darauf, dass es seine differenzielle Linksystematik bevorzugt. Das bedeutet, dass Sie die Links für die Stoppscripte und rc{scriptname} von Hand erzeugen müsen.

Das Beispiel

In einem privaten Netzwerk sollen alle angeschlossenen PCs, auf die gleiche Zeit synchronisiert werden. Dazu wurde einer dieser Rechner als Timeserver definiert. Dieser Rechner verfügt über ein Modem und soll sich selbst bei jeder Einwahl ins Internet, mit der Atomzeit abgleichen. Wenn der lokale Timeserver einmal nicht hochgefahren ist, sollen die anderen Rechner diesen Schritt der Initialisierungsphase übergehen. Dieses wurde als "kein Fehler" definiert, da die Zeitdifferenz, die innerhalb von ca. einer Woche durch die RTC-Uhr auf dem Motherboard vorhanden ist, als akzeptabel empfunden wird. Da der Zeitabgleich nur einmal beim Hochfahren des Systems ausgeführt werden soll, wurde auf viele der oben beschriebenen Optionen verzichtet. Dieses Script soll nur im Runlevel 5 ausgeführt werden. Als Programm fiel die Wahl auf das Programm "netdate" aus der Serie n.

Diesem Programm können Sie entweder eine IP-Adresse oder einen Domänennamen übergeben, damit es von dem angegebenen Rechner die Zeit holt. Da netdate die RFC868 Implementation auf dem Timeserver erwartet, sollte sichergestellt sein, dass der Zeitserver dieses auch unterstützt. Netdate holt zwar die Zeit von einem entfernten System ab, sobald Sie das System herrunterfahren, ist diese Zeitinformation aber verschwunden. Mit dem Programm /sbin/clock wird die RTC-Uhr auf Ihrem Motherboard mit der Zeit aus dem Programm netdate überschrieben.

Der Parameter -w legt die Zeitangabe als GMT (Greenwich Mean Time / Weltzeit) in der RTC ab, wobei der Parameter -wu diese Zeitangabe nach Ihren lokalen Gegebenheiten in der RTC ablegt. In diesem Beispiel wurden alle Rechner auf GMT-Zeit installiert und die Zeit über die lokalen Einstellungen erstellt. Dieses kann zu Verwirrungen führen, da Greenwich in Großbritannien liegt und somit eine andere Zeitzone besitzt. Wenn bei uns noch, vor Großbritannien, die Sommerzeit eingeführt wird, kann dieses zu einer Differenz Ihrer BIOS-Uhr von zwei Stunden führen, was aber absolut korrekt ist.

Zuerst wurde eine entsprechende Config-Datei im Verzeichnis /etc/rc.config.d angelegt, die alle Parameter benötigt, um die Scripte zu steuern. Ich benutze für derartige Aktionen meinen Nachnamen, da ich diesen auch immer am Ende einer Datei wiederfinde. Eine Liste aller über das Internet zu erreichenden Timeservern finden Sie unter der Adresse www.eecis.udel.edu/~mills/ntp/clock1.htm . Sie können hier mehrere Zeitserver angeben. Diese werden in den Scripten dann solange abgearbeitet, bis einer gefunden wurde, oder beendet, wenn keiner aktiv ist.

Datei: /etc/rc.config.d/zander.rc.config (chmod 744)
  
   #
   # Eintrag des FQDN des Zeitservers der benutzt werden soll
   # Mehrere Eintraege sind mit einem Space zu trennen.
   #
   ZANDER_NTP="time.fu-berlin.de"
  
   #
   # Bestimmung der Zugriffsart. Erlaubte Werte (local/ppp/ippp)
   # local = Zeitangabe aus dem Intranet holen
   # ppp   = Zeitangabe mittels einer PPP-Verbindung holen
   # ippp  = Zeitangabe mittels einer ISDN-Verbindung holen
   #
   ZANDER_NTP_ART="ppp"
  
   #
   # Absoluter Pfad und Name der LOG-Datei
   # Wenn kein Eintrag erfolgt, wird keine LOG-Datei erstellt
   #
   ZANDER_NTP_LOGDATEI=/var/log/ntp.log
  


Die nachfolgende Datei wird beim Start des Runlevel 5 aufgerufen. Die Funktion clearline bewirkt, das der Cursor eine Zeile auf dem Bildschirm nach oben wandert und anschließend die Zeile löscht. Gemäß den Daten aus der Datei /etc/rc.config.d/zander.rc.config wird ein Protokoll erstellt oder auch nicht. Dieses Script wird nur ausgeführt, wenn der Wert auf "local" gesetzt wurde. Mit der Anweisung

  >> ln -s ../ntpdate /etc/init.d/rc5.d/S90ntpdate 
  
muss der Link gesetzt werden.

Datei: /etc/init.d/ntpdate (chmod 755)
  
   #! /bin/sh
   #
   # /etc/init.d/ntpdate
   # Verwendet bei INIT 5
   #
   . /etc/rc.config.d/zander.rc.config
   . /etc/rc.status
   #
   # Network Time Protokoll activate after a Intranetconnection
   #
   clearline()  {
   	     printf ";\033[1A\033[2K";
   	     }
   
   rc_reset
   if test $ZANDER_NTP_ART = "local"; then
     # Begin Protocol
      if ! test $ZANDER_NTP_LOGDATEI = ""; then
         echo -n ";Adjust begin   : "			>> $ZANDER_NTP_LOGDATEI
         /sbin/clock					>> $ZANDER_NTP_LOGDATEI
      fi
      # Time update 
   
      ZANDER_TMP1="NOT TIMESERVER FOUND!"
      echo
    
      for ZANDER_TMP in `echo $ZANDER_NTP`
      do
          clearline
          echo "Calling NTP-Server $ZANDER_TMP"
          `/usr/sbin/netdate $ZANDER_TMP > /tmp/netdate.tmp 2>&1`
          if test `grep -c "failed" /tmp/netdate.tmp` = 0; then
             clearline
             echo -n "Starting NTP from $ZANDER_TMP"
             rc_status -v 
             ZANDER_TMP1=$ZANDER_TMP
             echo -n "Update RTC "
             /sbin/clock -uw
             rc_status -v
     	  break  
          else
             clearline
             echo -n "Update with Timeserver"
            rc_status -u
          fi
      done  
    
      # End Protocol 
   
      if test $ZANDER_NTP_LOGDATEI != ""; then
         echo -n "with Data      : "			>> $ZANDER_NTP_LOGDATEI
         /sbin/clock					>> $ZANDER_NTP_LOGDATEI
         echo "Timeserver     : "$ZANDER_TMP1             >> $ZANDER_NTP_LOGDATEI
         echo                                             >> $ZANDER_NTP_LOGDATEI
      fi
   
      # Cleaning 
      rm -f /tmp/netdate.tmp
   fi   
     
   rc_reset
   rc_exit
  


Um bei einer aktivierten Verbindung zum Internet den Zeitabgleich durchzuführen, sieht SuSE Linux eine Datei /etc/ppp/ip-up.local vor, die Sie noch manuell erstellen müssen, oder Sie editieren diese Datei /etc/ppp/ip-up direkt.

Auch diese Datei können Sie auf alle Rechner bringen, da der Script nur ausgeführt wird, wenn der entsprechende Parameter auf "ppp" oder "ippp" eingestellt ist. In der Configdatei existiert zwar bereits die Möglichkeit dieses auch über eine ISDN-Verbindung zu realisieren, aber aufgrund des Fehlens eines ISDN-Anschlusses konnte ich dieses nicht prüfen. Aber eine Modifizierung dürfte keine Probleme bereiten.

Das Script "ip-up" übergibt fünf Parameter an das Script "ip-up.local". Als erstes wird der Protokolltyp übergeben, welches die Verbindung hergestellt hat, gefolgt von den Daten des Device-Typs und der Übertragungsgeschwindigkeit. Zum Abschluss wird noch die zugewiesene IP-Adresse und die IP-Adresse des Gateways mit übergeben.

Datei: /etc/ppp/ip-up.local (chmod 755)
  
   #!/bin/sh
   #
   # This Parameters become this script from ip-up
   # $1 = Connection typ		(ppp0)
   # $2 = Connection device	(/dev/ttyS1)
   # $3 = Rate			(57600)
   # $4 = this IP-Adress 		(www.xxx.yyy.zzz)
   # $5 = IP-Adress Peer to Peer	(www.xxx.yyy.zzz)
   #
   . /etc/rc.config.d/zander.rc.config
   
   case "$1" in
   ppp*)
       #
       # Network Time Protocol activate after making a PPP-Conection
       #
       if test $ZANDER_NTP_ART = "ppp" then
          # ---------- Begin Protocol ----------------------------------------
          if ! test $ZANDER_NTP_LOGDATEI = "" then
             echo -n "Adjust begin : "		 >> $ZANDER_NTP_LOGDATEI
             /sbin/clock				 >> $ZANDER_NTP_LOGDATEI
          fi      
          # ---------- Time update -------------------------------------------
          ZANDER_TMP1="NOT TIMESERVER FOUND!"       
          for ZANDER_TMP in `echo $ZANDER_NTP`
          do 
            `/usr/sbin/netdate $ZANDER_TMP > /tmp/netdate.tmp 2>&1`
            if test `grep -c "failed" /tmp/netdate.tmp` = 0; then
               /sbin/clock -wu
   	    ZANDER_TMP1=$ZANDER_TMP
   	    break 
            fi	
          done
          # ---------- End Protocol ------------------------------------------
          if test $ZANDER_NTP_LOGDATEI != "" then
             echo -n "with Data    : "		 >> $ZANDER_NTP_LOGDATEI
             /sbin/clock				 >> $ZANDER_NTP_LOGDATEI
             echo "Timeserver   : "$ZANDER_TMP1	 >> $ZANDER_NTP_LOGDATEI
             echo					 >> $ZANDER_NTP_LOGDATEI
          fi      	
       fi	
       # ------------- Cleaning ---------------------------------------------- 
       rm -f /tmp/netdate.tmp
       ;;
   ippp*)
       ;;
   *)
       ;;
   esac
   
  



Quellen:

[1] Peter Samulat: Zeitsynchronisierung im Linux-Netzwerk, Linux-Magazin 12/2000, Seite126 ff

[2] Michael Plura: Atomzeit aus dem Netz, Linux-intern 2/2001, Seite 90 ff

Erklärungen:

Mount / Dismountent nennt man das Ein- und Aushängen eines Speichermediums (wie Disketten oder Partitionen) in den Linux-Verzeichnisbaum.

Ein symbolischer Link oder Verweis ist ein Verzeichniseintrag auf eine andere Datei. Dieser Eintrag enthält keine eigenen Daten. Daten enthält nur die Datei, auf die über den Link verwiesen wird.

Script: engl. "Protokoll, man bezeichnet damit allgemein Shell-Programme. Das Script ist stets eine Text-Datei, die man sich direkt anzeigen lassen kann.




Anmerkungen zu diesem Artikel


[1]  Skripte - Reihenfolge Abarbeitung Start-/StoppreihenfolgeFranzR12-11-2003


Eigene Anmerkung eintragen