Experimentieren mit Upstart unter Debian 5.0 Lenny

Diese Anleitung ist als Hilfe zum Einstieg für eigene Experimente mit Upstart auf einem Rechner mit Debian 5.0 Lenny gedacht.

Upstart ist ein Ersatz für SysV-Init, das Programm das nach dem Laden des Linux-Kernel als
erstes gestartet wird und direkt oder indirekt alle anderen Programme startet.

Achtung! In dieser Anleitung werden essentielle Systemprogramme ersetzt.
Es ist möglich, das der Rechner anschließend nicht mehr bis zum Anmeldebildschirm startet.
Daher ist diese Anleitung ausschließlich an erfahrene Anwender gerichtet.

Upstart übersetzen und installieren

Leider ist Upstart bei Debian erst in der momentanen Test-Distribution Squeeze enthalten. Ich nehme daher die Quellen von dort und übersetze Upstart selbst.

Als erstes nehme ich die Quellpakete von Debian Squeeze in /etc/apt/sources.list auf

$ sudo vim /etc/apt/sources.list

In dieser Datei füge ich die folgende Zeile hinzu, falls sie nicht schon enthalten ist.

deb-src http://ftp.de.debian.org/debian/ testing main non-free contrib

Als nächstes installiere ich einige Programme, die ich für das Übersetzen von Debian-Paketen im Allgemeinen benötige und noch ein paar, die für Upstart notwendig sind.

$ sudo aptitude install dpkg-dev fakeroot debhelper
$ sudo aptitude install quilt libdbus-1-dev

Das Übersetzen der für Upstart notwendigen Debian-Pakete ist dann recht einfach.

$ apt-get source –build upstart

Etwas problematischer ist die Installation, da Upstart ein Ersatz für SysV-Init ist und letzteres – ein essentielles Programm – dafür entfernt werden muss. Das Paketsystem von Debian ist darauf ausgerichtet, unerfahrene Anwender vor sich selbst zu schützen und daher muss ich dem Programm dpkg mit der Option –force-remove-essential mitteilen, dass ich SysV-Init wirklich ersetzen will.

$ sudo dpkg –force-remove-essential -i *.deb

Bluetooth auf Start durch Upstart umstellen

Da momentan noch recht wenig Software auf die Verwaltung durch Upstart umgestellt ist, hat es außer dem Lerneffekt wenig Sinn die oben genannten Schritte durchzugehen und die Stabilität seines Systems auf’s Spiel zu setzen. Wenn man nicht die Vorteile von Upstart wirklich nutzen will.

Auf meinem Netbook wird Bluetooth automatisch mit gestartet damit es beim Anstecken des Bluetoothsticks gleich verfügbar ist. Das kostet bei jedem Start etwa eine Sekunde bevor der Anmeldebildschirm da ist. Daher war das Bluetooth-System für mich die erste Software, die ich auf Upstart umgestellt habe.

Bei der Umstellung von Bluetooth habe ich mich von einem Artikel in der Zeitschrift c’t [1] inspirieren lassen.

Zunächst benötigen wir eine Regel für udev, mit deren Hilfe wir Ereignisse für Upstart generieren, wenn ein USB-Bluetoothstick angesteckt oder abgezogen wird.

sudo vim /etc/udev/rules.d/bluetooth.rule

Die Datei sieht bei mir wie folgt aus:

SUBSYSTEM=="bluetooth", SUBSYSTEMS=="usb", ACTION=="add", RUN+="/sbin/initctl --quiet emit --no-wait -e UDEV_KERNEL=$kernel -e UDEV_DEVPATH=$devpath bluetooth-device-add"
SUBSYSTEM=="bluetooth", SUBSYSTEMS=="usb", ACTION=="add", RUN+="/usr/bin/logger -- /sbin/initctl --quiet emit --no-wait -e UDEV_KERNEL=$kernel -e UDEV_DEVPATH=$devpath bluetooth-device-add"
SUBSYSTEM=="usb", ACTION=="remove", RUN+="/sbin/initctl --quiet emit --no-wait -e UDEV_DEVPATH=$devpath device-remove"
SUBSYSTEM=="usb", ACTION=="remove", RUN+="/usr/bin/logger -- /sbin/initctl --quiet emit --no-wait -e UDEV_DEVPATH=$devpath device-remove"

Die zweite und vierte Zeile (die mit /usr/bin/logger können entfallen, sind nur zum Zwecke der Fehlersuche da.

Als nächstes erzeugen wir eine Steuerdatei in /etc/event.d/, die die Ereignisse die von der udev-Regeldatei kommen, auswertet und daraus die Ereignisse bluetooth-start und bluetooth-stop generiert.

$ sudo vim /etc/event.d/bluetooth-device

Diese Datei sieht bei mir so aus:

# Start VDR only when at least one dvb device is present

env RUNDIR=/var/run/bluetooth

start on bluetooth-device-add
start on device-remove

emits bluetooth-start bluetooth-stop

script
  logger "upstart: bluetooth-device: $UPSTART_EVENT: $UDEV_KERNEL - $UDEV_DEVPATH"
  case "$UPSTART_EVENT" in
    bluetooth-device-add)
      if [ -n "$UDEV_KERNEL" -a -n "UDEV_DEVPATH" ]; then
        mkdir -p $RUNDIR
        # echo ${UDEV_DEVPATH%/dvb/dvb*.dvr0} > $RUNDIR/$UDEV_KERNEL
        echo ${UDEV_DEVPATH%/bluetooth/${UDEV_KERNEL}} > $RUNDIR/$UDEV_KERNEL
        logger "/sbin/initctl --quiet emit --no-wait bluetooth-start"
        /sbin/initctl --quiet emit --no-wait bluetooth-start
      fi
      ;;
    device-remove)
      if [ -d $RUNDIR ]; then
        logger "device-remove: UDEV_DEVPATH=$UDEV_DEVPATH"
        for d in $RUNDIR/*; do
          if [ -f $d ]; then
            read basedev < $d
            logger "device-remove: $d: basedev=$basedev"
            if [ -z "$basedev" -o "${UDEV_DEVPATH#${basedev}}" != "${UDEV_DEVPATH}" ]; then
              :
            else
              rm -f $d
            fi
          fi
        done
        rmdir --ignore-fail-on-non-empty $RUNDIR
        if [ ! -d $RUNDIR ]; then
          logger "/sbin/initctl --quiet emit --no-wait bluetooth-stop"
          /sbin/initctl --quiet emit --no-wait bluetooth-stop
        fi
      fi
      ;;
    esac
end script

Auch hier sind die Zeilen mit logger entbehrlich. Zur Funktionsweise der Datei siehe [1]

Als nächstes erzeugen wir eine Steuerdatei in /etc/event.d/ mit der das Bluetooth-System gestartet und beendet wird.

$ sudo vim /etc/event.d/bluetooth

Diese Datei sieht bei mir so aus:

# Starts Bluetooth

start on bluetooth-start
stop on bluetooth-stop
stop on runlevel 0
stop on runlevel 1
stop on runlevel 6

script
  logger "upstart: bluetooth: $UPSTART_EVENT"
  stop () {
    /etc/init.d/bluetooth stop
  }
  trap stop 15
  case "$UPSTART_EVENT" in
    bluetooth-start)
      /etc/init.d/bluetooth start
      while true; do
        sleep 10000;
      done
      ;;
#    bluetooth-stop)
#      /etc/init.d/bluetooth stop
#      ;;
  esac
end script

Upstart erwartet, dass ein gestarteter Dienst im Vordergrund bleibt im Gegensatz zu SysV-Init, welches erwartet, das sich ein via rc gestartetes Script aus /etc/init.d/ beendet, wenn der Dienst initialisiert ist. Beim Beenden eines Dienstes sendet Upstart diesem lediglich ein SIGTERM bzw. SIGKILL, wenn der Dienst sich nicht schnell genug beendet, während SysV-Init das gleiche Script wie zum Starten mit dem Parameter stop aufruft.

Da ich nicht das gesamte Script /etc/init.d/bluetooth nachprogrammieren wollte, adaptiere ich das Verhalten des Scripts für Upstart. Nachdem das Script /etc/init.d/bluetooth sich beendet hat, halte ich das Upstart-Script mit der while-Schleife am Leben. Wenn dieses Script ein SIGTERM-Signal erhält, wird via trap die Funktion stop() und darüber das SysV-Init-Script mit dem Parameter stop aufgerufen.

Bleibt als letztes, Bluetooth aus der Verwaltung durch die SysV-Init-Scripts zu entlassen.

$ sudo update-rc.d -f bluetooth remove

Literatur, Verweise

  1. Mirko Dölle; Bitzstarter; c’t Magazin für Computertechnik 2009, Heft 9, S. 176ff

Das könnte Dich auch interessieren …