0. Technische Aspekte von Mac OS X Inhaltsverzeichnis

0.4 Launchd, LaunchDaemons und LaunchAgents

Automatische Arbeiten im Hintergrund.

Stichwort-Liste

0.4.1 Einführung

Launchd ist der Hauptprozeß von Mac OS X. Er wurde mit 10.4 Tiger eingeführt und seit 10.5 Leopard sind auch die restlichen Systemdienste auf ihn umgestellt.

Im frühen UNIX hatte das Init-Programm nur drei- oder vierhundert Bytes. Im Laufe der Jahrzehnte wurde es jedoch immer größer und es sammelten sich diverse zusätzliche Initprogramme an, die typischerweise auf ".d" endeten, zum Beispiel "init", "init.d", "cron.d", "rc", "rc.d", "inet.d", "daily.out.d", "xinet.d", "systemstarter". Ihre Konfiguration war auch unterschiedlich. Nun gibt es nur noch ein "d": launchd.

Er kann andere Programme nach Bedarf starten (von "to launch", und "d" für daemon). So ein Bedarf kann sich auf verschiedene Weisen äußern: Feste Zeitpunkte, periodisch wiederkehrende Ausführungszeiten, Anfragen auf bestimmten Netzwerk-Ports oder Änderungen im Dateisystem.

Launchd bietet diverse Vorteile und Möglichkeiten:

"Für den durchschnittlichen UNIX-Hacker sieht launchd wahrscheinlich wie die Neuerfindung des Rades aus, aber es löst Probleme, von denen die UNIX-Welt nicht einmal wußte, daß es sie hat. Ähnlich wie es auch schon zuvor "UNIX für zuhause" gab, so ist Mac OS X doch in diesem Punkt einen Schritt weiter."

Frei übersetzt nach diesem Artikel von ars technica.

Apple hat launchd als Open-Source-Projekt nicht nur bei sich, sondern auch hier veröffentlicht. Apple hofft, daß launchd dadurch auch von anderen UNIX-Systemen übernommen wird. Launchd steht unter der Apache-Lizenz (Version 2.0), die den Nutzer praktisch weder einschränkt noch gängelt.

Seit circa April 2010 gibt es mit systemd eine Version, die das Konzept von launchd auch für GNU/Linux verfügbar macht. So wird systemd beispielsweise in Fedora 14 und 15 verwendet.

Siehe auch meinen Blogeintrag zur Nutzung von systemd in Linux-Distributionen.

0.4.2 Dämonen, Agenten und ihre Verzeichnisse

Dämonen arbeiten immer ohne sichtbare Oberfläche im Hintergrund. Agenten können auch in der graphischen Oberfläche auftauchen. Dämonen erfüllen systemweite Aufgaben und dienen nicht einem speziellen Benutzer. Von einem Agenten wird jeweils ein eigenes Exemplar für jeden Benutzer aktiv, der sich anmeldet.

Es gibt Dämonen und (seit 10.5 Leopard auch Agenten), die mit dem Betriebssystem ausgeliefert werden. Ferner sind Dämonen und Agenten möglich, die von Administratoren hinzugefügt werden. Und drittens sind Agenten (aber keine Dämonen) möglich, die ein normaler Benutzer für sich allein installiert.

Ob ein Dämon beziehungsweise Agent vom System, einem Administrator oder einem Benutzer kam, erkennt man am Verzeichnis, in dem sie liegen:

All diese Verzeichnisse werden automatisch von launchd eingelesen.

Wie grundsätzlich, so gilt auch hier: Niemand, auch kein Administrator, hat in Verzeichnissen von /System/Library und darunter etwas zu ändern. Es ist auch nicht nötig, denn den gleichen systemweiten Effekt erzielen Administratoren, wenn sie in /Library arbeiten. So sind die Bereiche, die vom System definiert werden und die, die von Administratoren bearbeitet werden, sauber getrennt.

Vergleiche dazu Apples Artikel Getting Started with launchd.

Wem das nicht einleuchtet, der möge sich bewußt machen, das etwaige Änderungen in /System/Library durch Aktualisierungen des Betriebssystems jederzeit vernichtet werden, während Änderungen in /Library erhalten bleiben. Genauso wie natürlich Änderungen in ~/Library erhalten bleiben, die Benutzer für sich allein vornehmen. Die Trennung dient auch der Stabilität des Systems.

0.4.3 Kommando-Zentrale für launchd

Mit launchctl bekommt man die Kommando-Zentrale, um mit launchd "zu reden". Der Name dürfte die Abkürzung für "launch control" sein.

Ein Administrator kann mit sudo launchctl mit der Instanz von launchd, die systemweit (als root) tätig ist, reden. Wenn man launchctl allein eingibt, dann redet man mit der Instanz von launchd, die für den Benutzer tätig ist, der launchctl gerade aufrief.

Mit ls /var/launchd kann man sich die Benutzer-Identitäts-Nummern ansehen, für die eine Instanz von launchd läuft. Die 0 entspricht root, also dem System.

Verlassen kann man launchctl durch control-d. Hier sind einige nützliche Kommandos, die man in launchctl verwenden kann:

"Geladen" und "gestartet" ist ein Unterschied. Ein Dämon oder Agent wird von launchd verwaltet, wenn er geladen wurde. Er kann manuell geladen werden oder (das ist der Normalfall) dadurch, daß seine Konfigurationsdatei in einem der Standardverzeichnisse liegt.

Ein geladener also von launchd verwalteter Agent oder Dämon wird gestartet/aktiv, also seine Tätigkeit durchgeführt, wenn er manuell gestartet wird oder (das ist der Normalfall) wenn eine Situation eintritt, die in seiner Konfigurationsdatei definiert wurde (Zeitpunkt, Intervall, Netzanfrage, Dateiänderung und so weiter).

0.4.4 Zugriffsrechte für Dämonen und Agenten

Dämonen und Agenten, die ein Administrator in /Library/LaunchDaemons beziehungsweise in /Library/LaunchAgents installiert, sollten folgende Zugriffsrechte aufweisen:

Eigentümer ist root und Gruppe is wheel. Verzeichnisse und ausführbare Dateien sollten nur für root änderbar sein, also 755 (rwxr-xr-x). Dateien sollten nur von root änderbar und von niemandem ausführbar sein, also 644 (rw-r--r--).

Vergleiche dazu Apples Artikel Daemons and Agents.

Diese Einstellungen dienen dazu, daß ein normaler Benutzer nicht durch die Veränderung eines Dämons höhere Rechte erlangen kann.

0.4.5 Praktische Beispiele von LaunchDaemons und LaunchAgents

Ich stelle nun einige LaunchDaemons und LaunchAgents vor, die ich für mich erstellt habe und verwende. Sie können als Vorlage für ähnliche Aufgaben dienen.

Agenten und Dämonen bestehen aus mindestens einer XML-Datei, die man per Hand oder komfortabel mit Hilfe des Property List Editors, der Teil der Developer Tools (Xcode) ist, erstellen kann. Umfangreichere Agenten und Dämonen nutzen zusätzlich noch Shell-Skripte. Diese Shell-Skripte werden typischerweise in /usr/local/bin abgelegt.

Vergleiche dazu den Abschnitt "Why are there 7 binaries directories?" des Artikels Mac OS X Hidden Files & Directories.

0.4.5.1 Dämon: Netzwerk für DSL optimieren

Dieser Dämon konfiguriert beim Start des Rechners die Netzwerk-Einstellungen von Mac OS X so, daß sie optimal sind für schnelle Internetverbindungen wie beispielsweise DSL.

Man kann diese Netzwerk-Werte auch in der Datei /etc/sysctl.conf setzen. Dabei verwendet man Zeilen wie beispielsweise net.inet.tcp.sendspace=49152. Die Datei ist normalerweise noch nicht vorhanden und da sie während des Rechnerstarts gelesen wird, sollte der Besitzer root und die Gruppe wheel sein und die Rechte 0644.

Ab 10.6 bieten die Sytem-Einstellungen Einstellmöglichkeiten für die MTU-Werte auch für das Funknetz.

Der Dämon besteht aus zwei Dateien. In /Library/LaunchDaemons liegt die XML-Definition des Dämons in der Datei de.realmacmark.dslnet.plist.

Die Endung ".plist" signalisiert eine Voreinstellungsdatei (Preference List). Der Name folgt Apples Empfehlung, umgekehrte Domain-Namen zu verwenden, um eindeutige Namen zu garantieren.

Der Inhalt ist:

<?xml version="1.0" encoding="UTF-8"\?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>de.realmacmark.dslnet</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/dslnet_optimizer.sh</string>
</array>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>

Im Property List Editor sieht es so aus:

DSLnet.plist XML in Property List Editor

Das Label legt den Namen des Dämons fest, unter dem launchd ihn kennen soll. Der Program-Eintrag definiert die Tätigkeit des Dämons und RunAtLoad sorgt dafür, daß die Tätigkeit des Dämons auch schon einmal beim Laden des Dämons ausgeführt werden soll.

Alle verfügbaren Einstellungsmöglichkeiten für Dämonen kann man sich mit man launchd.plist anzeigen lassen.

Die zweite Datei ist dslnet_optimizer.sh, die man im Verzeichnis /usr/local/bin speichert und mit sudo chmod +x dslnet_optimizer.sh ausführbar macht.

Dies ist Version 1.3 meines Shell-Skriptes:

#!/bin/sh
/usr/sbin/sysctl -w net.inet.tcp.sendspace=65536 > /dev/null
/usr/sbin/sysctl -w net.inet.tcp.recvspace=65536 > /dev/null
/usr/sbin/sysctl -w kern.ipc.maxsockbuf=524288 > /dev/null
/usr/sbin/sysctl -w net.inet.tcp.delayed_ack=0 > /dev/null
/usr/sbin/sysctl -w net.inet.udp.recvspace=73728 > /dev/null
/sbin/ifconfig en0 mtu 1492 > /dev/null
/bin/sleep 15 > /dev/null
/sbin/ifconfig en1 mtu 1484 > /dev/null
/usr/bin/say -v Boing network settings optimized > /dev/null

Hier werden die Netzwerkeinstellungen gesetzt. Vergleiche dazu meine Seite über "Maximale Geschwindigkeit mit Breitband-Internet", auf der die gesetzten Werte erläutert werden. Das Setzen dieser Werte ist mit solch einem LaunchDaemon am elegantesten. Vor dem Einstellen des Wertes für die Funkverbindung wartet das Skript 15 Sekunden, um nicht zu früh vergeblich zuzugreifen.

Eventuelle Ausgaben der Befehle werden mit > /dev/null an ein nicht-existierendes Gerät geschickt, also ignoriert. Die letzte Zeile nutzt die Sprachausgabe, um mit der Stimme (-v bedeutet voice) von "Boing" (der Name entspricht denen, die man in den Systemeinstellungen findet) den Erfolg zu melden.

Wenn man den Dämon soweit per Hand eingerichtet hat, dann kann man sich einen Neustart ersparen, indem man ihn selbst lädt:

sudo launchctl load /Library/LaunchDaemons/de.realmacmark.dslnet.plist

dslnet disk image

Hier ist ein Installations-Programm von mir, das den oben beschriebenen Dämon installiert.

Die Sprachausgabe ist in dieser Version auskommentiert. Ein Neustart ist nach der Installation nicht nötig, denn der Dämon wird nach der Installation sofort geladen.

MD5-Prüfsumme 0186b616bca619991e08706dd6503d7d.

0.4.5.2 Dämon: Automatischer Aufruf einer Internet-Adresse

Dieser Dämon ruft beim Start des Rechners und danach alle zehn Minuten eine bestimmte Internetseite auf und übergibt ihre einige Daten. Einige Macs melden auf diese Weise ihre aktuelle IP-Adresse an meiner Homepage an, so daß ich jederzeit per SSH Fernwartung machen kann.

Der Dämon besteht aus zwei Dateien. In /Library/LaunchDaemons liegt die XML-Definition des Dämons in der Datei de.realmacmark.ips.plist.

Der Inhalt ist:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>de.realmacmark.ips</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/publish_ip.sh</string>
<string>http://www.realmacmark.de/geheim.php</string>
<string>rechner=bigbadbabyboy</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>StartInterval</key>
<integer>600</integer>
<key>UserName</key>
<string>nobody</string>
</dict>

Der Inhalt dieses Beispiels ist natürlich etwas verändert, um keine Interna meiner Homepage zu veröffentlichen.

Im Property List Editor sieht es so aus:

ips.pnet XML in Property List Editor

Der ProgramArguments-Eintrag hat als ersten Untereintrag das aufzurufende Programm und als folgende Untereinträge die Parameter an das Programm. Auch dieser Dämon ist so konfiguriert, daß er seine Aufgabe bereits einmal ausführt, wenn er selbst geladen wird. Außerdem führt er das Programm alle 600 Sekunden erneut aus.

Da das Programm, was der Dämon ausführt (curl), keine besonderen Rechte benötigt, um zu funktionieren, habe ich als Benutzer, der das Programm ausführen soll, den vom System für solche Zwecke bereitgehaltenen nobody gewählt.

Die zweite Datei ist publish_ip.sh, die ich im Verzeichnis /usr/local/bin gespeichert und mit sudo chmod +x publish_ip.sh ausführbar gemacht habe.

#!/bin/sh
/bin/sleep 30
/usr/bin/curl $1\?$2 > /dev/null

Das Skript macht am Anfang 30 Sekunden Pause, um nicht zu früh auf das Netzwerk zuzugreifen und außerdem, um launchd nicht den Eindruck zu geben, es wäre sofort abgestürzt, weil es zu schnell beendet wird. Dann ruft es eine Adresse im Internet auf, die sich aus dem ersten Parameter, der an dieses Skript übergeben wurde, einem Fragezeichen (das leitet die Parameterliste am Ende einer Web-Adresse ein) und dem zweiten Parameter zusammensetzt.

0.4.5.3 Agent: Sprachausgabe zur Begrüßung

Dieser Agent begrüßt jeden Benutzer, wenn er sich am System anmeldet, per Sprachausgabe.

Für diesen Agenten mußte ich nur eine Datei selbst erstellen, weil ich für seine Funktionalität auf ein bereits vorhandenes Shell-Skript zurückgreife: In /Library/LaunchAgents lege ich die XML-Definition des Agenten in der Datei de.realmacmark.say.plist ab.

Der Inhalt ist:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>de.realmacmark.say</string>
<key>ProgramArguments</key>
<array>
<string>/usr/bin/say</string>
<string>-v</string>
<string>Vicki</string>
<string>Welcome to Macintosh</string>
</array>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>

Im Property List Editor sieht es so aus:

Say.plist XML in Property List Editor

Ein Agent wird von launchd immer, wenn sich ein neuer Benutzer am Rechner anmeldet, für diesen individuell (als Kopie) geladen. Dieser Agent ist so eingestellt, daß er seine Aufgabe (say) ausführt, wenn er selbst geladen wird. Ein periodisches oder wiederholtes oder datumsgesteuertes Ausführen wäre natürlich auch (zusätzlich) möglich.

Dem Programm say wird als Parameter übergeben, daß es die Stimme von Vicki verwenden soll, um "Welcome to Macintosh" zu sagen.

Valid XHTML 1.0!

Besucherzähler


Latest Update: 11. September 2015 at 19:51h (german time)
Link: cnc.realmacmark.de/osx_launchd.php