ubuntuusers.de

ubuntuusers.deWikiUpstart

Upstart

Dieser Artikel wurde für die folgenden Ubuntu-Versionen getestet:

Zum Verständnis dieses Artikels sind folgende Seiten hilfreich:

./upstart_logo.png

Upstart {en} ist ein Ubuntu-Projekt, welches den Systemstart von Ubuntu bzw. allgemein Linux beschleunigt. Mittel- bis langfristig soll Upstart auch noch weitere Aufgaben im Linux-System übernehmen.

Wie Upstart arbeitet

Beim Systemstart werden eine Reihe von Programmen und Diensten gestartet (z.B. der XServer für die Grafik, der CUPS-Daemon zum Drucken etc.), bevor man mit dem System arbeiten kann. Traditionell werden diese Programme bzw. Dienste über eine in den Runleveln des klassischen SysV-Init-Systems festgelegte Reihenfolge geladen. Das Laden erfolgt dabei linear, d.h. ein Dienst nach dem anderen.

Upstart verwendet einen neuen Ansatz, um den Systemstart zu beschleunigen. Programme und Dienste werden ereignisbasiert geladen und gestartet, wodurch mehrere – voneinander unabhängige – Dienste parallel gestartet werden können. Hierdurch wird die Startgeschwindigkeit verbessert.

Upstart unter Ubuntu

Seit Ubuntu 6.10 Edgy Eft ist Upstart fester Bestandteil von Ubuntu und wird standardmäßig zum Systemstart eingesetzt (wobei 6.10 die erste Linux-Distribution überhaupt war, in der Upstart eingesetzt wurde). In Ubuntu 7.04 Feisty Fawn wurde eine verbesserte Version von Upstart eingesetzt, mit Ubuntu 9.04 Jaunty Jackalope wurde der Bootvorgang durch eine optimierte Hardwareerkennung und eine teilweise Parallelisierung der Startskripte deutlich beschleunigt. Anfang März 2011 wurde Upstart 1.0 veröffentlicht, die aktuelle Version unter Precise ist Upstart 1.5.

Die Beschleunigung des Systemstarts ist erst der Anfang. Mittel- bis langfristig soll Upstart zum zentralen System von Ubuntu (und Linux) zur Verwaltung von Ereignissen ausgebaut werden. Dazu soll Upstart z.B. enger mit dem ACPI- und APM-Daemon als auch mit udev zusammenarbeiten. Außerdem könnte Upstart als universelles System andere ereignisbasierte Dienste wie at und cron ablösen.

Systemstart

Upstart ersetzt das klassische SysV-Init-System und damit auch die Start-/Stop-Mechanismen von Diensten. Allerdings sind noch lange nicht alle Dienste auf Upstart umgestellt, sondern vorrangig die zum Systemstart ("Init-Jobs") erforderlichen. Die Datei /etc/inittab entfällt. Wann ein Init-Job aktiv wird, legen Konfigurationsdateien im Ordner /etc/init/ (bisher /etc/event.d/) fest. Alle Dateien im Ordner /etc/init werden automatisch gestartet. Man muss also z.B. neue Skripte nicht mehr umständlich aktivieren, wie es früher der Fall war.

Das zentrale Werkzeug ist nun initctl, das Init-Jobs startet oder stoppt, Signale verschickt und den Status abfragt. So gibt beispielsweise der Befehl [1]:

initctl list 

eine Liste aller Init-Jobs und ihres Status aus:

mountall-net stop/waiting
rc stop/waiting
rsyslog start/running, process 10856
tty4 start/running, process 1132
udev start/running, process 10894
upstart-udev-bridge start/running, process 389
ureadahead-other stop/waiting
avahi-daemon start/running, process 11169
hwclock-save stop/waiting
tty5 start/running, process 1140
apport stop/waiting
atd start/running, process 1169
dbus start/running, process 683
failsafe-x stop/waiting
control-alt-delete stop/waiting
hwclock stop/waiting
network-manager start/running, process 824
usplash stop/waiting
module-init-tools stop/waiting
cron start/running, process 1170
gdm start/running, process 836
mountall stop/waiting
acpid start/running, process 1161
rcS stop/waiting
ufw start/running
hal stop/waiting
rc-sysinit stop/waiting
anacron stop/waiting
tty2 start/running, process 1156
udevtrigger stop/waiting
rsyslog-kmsg start/running, process 556
tty3 start/running, process 1157
udev-finish stop/waiting
hostname stop/waiting
mountall-reboot stop/waiting
mountall-shell stop/waiting
network-interface (lo) start/running
network-interface (eth0) start/running
tty1 start/running, process 1370
udevmonitor stop/waiting
dmesg stop/waiting
networking stop/waiting
procps stop/waiting
tty6 start/running, process 1159
ureadahead stop/waiting

Dementsprechend werden mit

sudo initctl [start | stop] Init-Job 

Init-Jobs gestartet bzw. beendet.

Trotz Upstart ist Ubuntu nicht ganz frei von "klassischen" Init-Skripten. Diese werden ebenfalls von Upstart zur gegebenen Zeit aufgerufen. Weitere Informationen zu diesem Thema findet man im Artikel Dienste.

Verhalten von Upstart beeinflussen

Möchte man bestimmte Init-Jobs abändern, so muss man die entsprechende Konfigurationsdatei im Verzeichnis /etc/init/ editieren.

Achtung!

Änderungen bitte mit Bedacht, entsprechenden Vorsichtsmaßnahmen und nie ohne Backup vornehmen. Schlimmstenfalls droht ein nicht mehr startendes System.

Run-Level ändern

Um zu verhindern, dass ein Dienst in einem bestimmten Run-Level gestartet wird, öffnet man die entsprechende .conf-Datei und editiert die Zeile

start on runlevel [2345]

Die Zahlen in den eckigen Klammern, repräsentieren dabei die Runlevel.

Entsprechend sollte auch die Zeile

stop on runlevel [!2345]

geändert werden. Das Ausrufezeichen in der Stop-Anweisung bedeutet, dass der Dienst gestoppt wird, wenn sich der Run-Level außerhalb der Aufzählung befindet. Upstart überwacht die Konfigurationsdateien mittels inotify, so dass man beim Testen der Änderungen folgende Meldung erhält:

initctl: Unknown job: Init-Job

Erst mit einem Neustart liest Upstart die geänderten Dateien ein. Schneller (und ohne Rechner-Neustart) geht es mit folgendem Befehl:

sudo initctl reload-configuration 

Abhängigkeiten von anderen Prozessen steuern

Wie die unten aufgeführten Beispiele zeigen, kann Upstart ein Programm oder einen Prozess entweder mit "exec" ausführen oder über ein Skript starten. Dieses Skript befindet sich dann in den Zeilen zwischen den Schlüsselwörtern "script" und "end script". Wenn es nötig ist, dass ein Prozess erst nach einem bestimmten Ereignis startet, dann gibt es prinzipiell zwei Wege:

Entweder erstellt man sich ein eigenes Upstart-Skript und fügt dessen erfolgte Ausführung als weitere Start-Bedingung in die oben beschriebene "start on" Zeile der abhängigen Datei jobname.conf ein. Hierbei sind auch komplexe logische Verknüpfungen {en} möglich, was beispielsweise innerhalb der Datei gdm.conf (hier am Beispiel von Ubuntu 10.04) sehr anschaulich zu sehen ist:

# gdm - GNOME Display Manager
#
# The display manager service manages the X servers running on the
# system, providing login and auto-login services

description	"GNOME Display Manager"
author		"William Jon McCann <mccann@jhu.edu>"

start on (filesystem
          and started dbus
          and (drm-device-added card0 PRIMARY_DEVICE_FOR_DISPLAY=1
               or stopped udevtrigger))
stop on runlevel [016]

emits starting-dm

env XORGCONFIG=/etc/X11/xorg.conf

script
    if [ -n "$UPSTART_EVENTS" ]
    then
	[ ! -f /etc/X11/default-display-manager -o "$(cat /etc/X11/default-display-manager 2>/dev/null)" = "/usr/sbin/gdm" ] || { stop; exit 0; }

	# Check kernel command-line for inhibitors
	for ARG in $(cat /proc/cmdline)
	do
	    case "${ARG}" in
		text|-s|s|S|single)
		    plymouth quit || :  # We have the ball here
		    exit 0
		    ;;
	    esac
	done
    fi

    if [ -r /etc/default/locale ]; then
	. /etc/default/locale
	export LANG LANGUAGE
    elif [ -r /etc/environment ]; then
	. /etc/environment
	export LANG LANGUAGE
    fi
    export XORGCONFIG

    exec gdm-binary $CONFIG_FILE
end script

Dabei ist aber zu beachten, dass nur das Schlüsselwort "starting" den Moment bezeichnet, an dem der Referenzprozess gestartet wird und das im Beispiel gezeigte Schlüsselwort "started" einen (beliebigen) Moment, nachdem der Referenzprozess gestartet wurde. "started" wartet also nicht so lange, bis der referenzierte Prozess fertig abgearbeitet ist.

Alternativ kann man auch in die betreffende jobname.conf ein "pre-start script" einfügen, wie es in der Datei mysql.conf (auch wieder am Beispiel von Ubuntu 10.04) schön zu sehen ist:

# MySQL Service

description     "MySQL Server"
author          "Mario Limonciello <superm1@ubuntu.com>"

start on (net-device-up
          and local-filesystems
	  and runlevel [2345])
stop on runlevel [016]

respawn

env HOME=/etc/mysql
umask 007

pre-start script
    #Sanity checks
    [ -r $HOME/my.cnf ]
    [ -d /var/run/mysqld ] || install -m 755 -o mysql -g root -d /var/run/mysqld
    # Load AppArmor profile
    if aa-status --enabled 2>/dev/null; then
        apparmor_parser -r /etc/apparmor.d/usr.sbin.mysqld || true
    fi
    LC_ALL=C BLOCKSIZE= df --portability /var/lib/mysql/. | tail -n 1 | awk '{ exit ($4<4096) }'
end script

exec /usr/sbin/mysqld

post-start script
    for i in `seq 1 30` ; do
        /usr/bin/mysqladmin --defaults-file="${HOME}"/debian.cnf ping && {
            exec "${HOME}"/debian-start
            # should not reach this line
            exit 2
        }
        sleep 1
    done
    exit 1
end script

Das Pre-Start-Skript wird erst komplett abgearbeitet, bevor der "exec"-Befehl ausgeführt wird.

Möchte man beispielsweise sicherstellen, dass ein Dateiserver oder NAS nach dessen Wake-On-LAN bereits online ist, bevor man sich am Client anmelden kann (bspw. damit die Netzlaufwerke während des Startprozesses korrekt eingebunden werden können), dann kann man das durch ein entsprechendes Pre-Start Skript, das man in die gdm.conf einfügt, erreichen (Beispiel). Die Folge ist, dass die Anmelde-Maske erst dann erscheint, wenn der Dateiserver oder NAS erfolgreich mit ping erreicht werden konnten.

Deaktivieren von Init-Jobs

Wenn man Init-Jobs dauerhaft deaktivieren möchte, kann man entweder

  • die Datei /etc/init/jobname.conf umbenennen bzw. deren Endung .conf entfernen oder

  • innerhalb der Datei jobname.conf die Zeile mit "start on" auskommentieren

Zum Reaktivieren diese Änderungen rückgängig machen.

Ab Upstart 1.3 bzw. Ubuntu 11.10 existiert noch eine dritte Variante: .override-Dateien. Beispiele:

echo "manual" | sudo tee /etc/init/jobname.override 

oder

sudo sh -c "echo 'manual' > /etc/init/jobname.override" 

Der Vorteil gegenüber den ersten beiden Varianten ist, dass die Originaldatei /etc/init/jobname.conf nicht verändert wird. Möchte man einen Init-Job wieder aktivieren, löscht man einfach die .override-Datei (oder entfernt das Schlüsselwort "manual" in dieser Datei).

Beispiele

Wer ein eigenes Upstart-Skript schreiben möchte, braucht neben guten Englisch-Kenntnissen auch Beispiele. Nachfolgend ein erster Versuch, abzuspeichern als /etc/init/hallo_welt.conf:

# Meine ersten Schritte mit Upstart
description	"simples Upstart-Beispiel"
# wann starten bzw. stoppen?
start on runlevel [2345]
stop on runlevel [!2345]
env enabled=1
PATH_BIN=/bin/bash
exec echo "Hallo Welt $(date)" > /var/log/hallo_welt.log

Hiermit wird einfach der Text "Hallo Welt" und das aktuelle Datum in die Datei /var/log/hallo_welt.log geschrieben. Natürlich bringt ein solches Beispiel keinen konkreten Nutzen, aber vielleicht erleichtert es den Einstieg in Upstart.

Ein weiteres Beispiel aus dem Artikel Trackpoint zeigt das Ändern von Werten im Sysfs:

description "Trackpoint-Einstellungen"
start on virtual-filesystems
env TPDIR=/sys/devices/platform/i8042/serio1/serio2
script
  while [ ! -f $TPDIR/sensitivity ]; do
	sleep 2
  done
  echo -n 200 > $TPDIR/sensitivity
  echo -n 150 > $TPDIR/speed
  echo -n 1 > $TPDIR/press_to_select
end script

Kritik

So bestechend die Idee von Upstart bei mobilen und Desktop-Rechnern ist, gibt es insbesondere beim Einsatz auf Servern auch Probleme. Zum einen werden diese im Regelfall eher selten neu gestartet, so dass ein schnellerer Bootvorgang nur eine untergeordnete Rolle spielt. Zum anderen hat sich das klassische SysV-Init-System in der Praxis seit Jahrzehnten bewährt, auch wenn es definitiv nicht mehr zeitgemäß ist. Durch die Parallelisierung von Upstart lassen sich viele Dienste nicht mehr so einfach wie beim hierarchischen "Step-by-Step" aufeinander abstimmen bzw. erfordern einen höheren Konfigurationsaufwand.

Bei mancher Hardware kann es bei einer etwas unglücklichen Konfiguration beim Starten zu "Race Conditions" kommen, d.h. es wird versucht irgend etwas zu machen, noch bevor das benötigte dafür bereit ist – in sehr seltenen Fällen kann das dann schon mal sporadisch ("nur so") vorkommen. Schuld sind hier meistens die Bemühungen, den Startprozess durch Parallelisierung zu beschleunigen.

Zur Beschleunigung des Startvorgangs gibt es mit systemd einen ernsthaften Konkurrenten. Bisher setzt Ubuntu exklusiv auf Upstart, während beispielsweise Arch Linux, Fedora und OpenSuse auf systemd setzen. Nach Ubuntu 14.04 wird daher auch Ubuntu zu systemd wechseln.

Problembehebung

Job unbekannt

Nach Änderungen an bestehenden Skripten oder bei eigenen Skripten erscheint trotz Einlesen der neuen Konfiguration die Fehlermeldung

"initctl: Unknown job: hallo_welt"

Es liegt eventuell ein Fehler in der Syntax vor. Das Skript lässt sich mit folgendem Befehl prüfen:

init-checkconf hallo_welt.conf 

rc.local

Vom asynchronen Systemstart sind auch Anweisungen betroffen, die via /etc/rc.local ausgeführt werden sollen. Obwohl ein eigenes Upstart-Skript die bessere und zukunftssichere Lösung wäre, kann man betroffene Dienste oder Programme auch einfach zeitverzögert (neu) starten. Wie das konkret geht, ist im Artikel rc.local beschrieben.

Logdateien

Upstart legt für viele Dienste Logdateien in /var/log/upstart/ an.

Diese Revision wurde am 19. Februar 2014 08:35 von aasche erstellt.
Die folgenden Schlagworte wurden dem Artikel zugewiesen: System, Systemstart