macOS LaunchAgent nach Projektumzug sicher aktualisieren
Ein Projektpfad ändert sich, aber der Hintergrunddienst zeigt noch auf den alten Ort. Mit einer kontrollierten Pause, zwei Pfadänderungen und einem vollständigen Readback bleibt der Autostart belastbar.
2 Pfade prüfen · mit Rollback · 6 Minuten
Oliver Nagel · geprüft am
Warum beide Pfade zählen
Abschnitt betitelt „Warum beide Pfade zählen“Ein LaunchAgent kann den Projektort an mehreren Stellen referenzieren. ProgramArguments enthält häufig den absoluten Pfad zum gestarteten Programm; WorkingDirectory legt fest, in welches Verzeichnis launchd vor dem Start wechselt. Wird nur einer davon geändert, kann der Dienst mit einem veralteten Pfad scheitern oder im falschen Kontext laufen.
Per-User-Agents liegen im Benutzerkontext unter ~/Library/LaunchAgents. Sie werden in der GUI-Domain des angemeldeten Benutzers registriert. Für systemweite, benutzerunabhängige Dienste gelten andere Pfade und Berechtigungen.
Preflight: erst Ziel und Zustand klären
Abschnitt betitelt „Preflight: erst Ziel und Zustand klären“Vor dem Stoppen müssen Quelle, Agent-Datei und freier Zielpfad feststehen. Bei einem Git-Projekt schützt ein sauberer Arbeitsbaum davor, lokale Änderungen beim Verschieben aus dem Blick zu verlieren.
set -euo pipefail
label="com.example.project-web"agent="$HOME/Library/LaunchAgents/$label.plist"old_root="/Users/you/Projects/project-web"new_root="/Users/you/Projects/dev/project-web"
test -d "$old_root"test -f "$agent"test ! -e "$new_root"git -C "$old_root" diff --quietgit -C "$old_root" diff --cached --quietplutil -lint "$agent"Die Beispielwerte werden an das eigene Label, die Agent-Datei und die beiden absoluten Projektpfade angepasst. ProgramArguments.1 wird später nur dann verwendet, wenn dort laut plutil -p "$agent" tatsächlich der Programmpfad steht.
Sicherer Ablauf
Abschnitt betitelt „Sicherer Ablauf“Der Agent wird zuerst aus der GUI-Domain entfernt. Danach wird das Projekt verschoben und die Definition mit plutil angepasst. Erst eine syntaktisch gültige Plist wird wieder registriert.
set -euo pipefail
label="com.example.project-web"agent="$HOME/Library/LaunchAgents/$label.plist"old_root="/Users/you/Projects/project-web"new_root="/Users/you/Projects/dev/project-web"
launchctl bootout "gui/$(id -u)/$label" 2>/dev/null || true
mv "$old_root" "$new_root"
plutil -replace ProgramArguments.1 \ -string "$new_root/node_modules/vite/bin/vite.js" \ "$agent"plutil -replace WorkingDirectory \ -string "$new_root" \ "$agent"
plutil -lint "$agent"launchctl bootstrap "gui/$(id -u)" "$agent"launchctl kickstart -k "gui/$(id -u)/$label"Nicht nur den Prozess, auch den Dienst prüfen
Abschnitt betitelt „Nicht nur den Prozess, auch den Dienst prüfen“launchctl print bestätigt Zustand, Arbeitsverzeichnis und Prozess-ID. Der HTTP-Readback prüft zusätzlich, ob der eigentliche Dienst antwortet. Die abschließende Textsuche findet vergessene Pfadkopien – etwa eine im Repository mitgeführte Agent-Vorlage.
label="com.example.project-web"agent="$HOME/Library/LaunchAgents/$label.plist"old_root="/Users/you/Projects/project-web"new_root="/Users/you/Projects/dev/project-web"
launchctl print "gui/$(id -u)/$label" \ | grep -E 'state =|working directory =|pid ='
curl -fsS http://127.0.0.1:4173/ >/dev/null
rg --fixed-strings "$old_root" "$agent" "$new_root" \ --glob '!node_modules/**'Die letzte rg-Suche soll keine Fundstelle mit dem alten Pfad liefern. Ein Treffer ist kein kosmetischer Rest: Er kann beim nächsten Installieren oder Neustart wieder zur falschen Definition werden.
Typische Fehlerbilder
Abschnitt betitelt „Typische Fehlerbilder“bootstrap failed: 5
Abschnitt betitelt „bootstrap failed: 5“Zuerst die Plist mit plutil -lint prüfen und danach kontrollieren, ob alle absoluten Pfade existieren. Der generische Fehler allein benennt die eigentliche Ursache nicht.
Der Agent läuft, aber HTTP bleibt offline
Abschnitt betitelt „Der Agent läuft, aber HTTP bleibt offline“Dann ist die Prozessregistrierung erfolgreich, nicht zwingend die Anwendung. Fehlerlog, Portbindung und den direkten lokalen Endpunkt separat prüfen.
Nach einem Neustart ist wieder der alte Pfad aktiv
Abschnitt betitelt „Nach einem Neustart ist wieder der alte Pfad aktiv“Meist wurde nur die installierte Plist geändert, während eine zweite Vorlage oder ein Installationsskript im Projekt den alten Pfad enthält. Deshalb gehört die Pfadsuche zur Abschlussprüfung.
Rollback
Abschnitt betitelt „Rollback“Wenn der neue Ort nicht funktioniert, wird der Agent erneut gestoppt, das Projekt zurückverschoben und die ursprüngliche Definition wieder registriert.
set -euo pipefail
label="com.example.project-web"agent="$HOME/Library/LaunchAgents/$label.plist"old_root="/Users/you/Projects/project-web"new_root="/Users/you/Projects/dev/project-web"
launchctl bootout "gui/$(id -u)/$label" 2>/dev/null || truemv "$new_root" "$old_root"
plutil -replace ProgramArguments.1 \ -string "$old_root/node_modules/vite/bin/vite.js" \ "$agent"plutil -replace WorkingDirectory \ -string "$old_root" \ "$agent"
plutil -lint "$agent"launchctl bootstrap "gui/$(id -u)" "$agent"launchctl kickstart -k "gui/$(id -u)/$label"Danach dieselben Prozess- und HTTP-Prüfungen aus dem Verifikationsschritt wiederholen.
Quellen
Abschnitt betitelt „Quellen“- Apple: Creating Launch Daemons and Agents
- Apple: Designing Daemons and Services
- Vite: Deploying a Static Site
man launchctlundman launchd.plistauf dem geprüften macOS-System