Zum Inhalt springen

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

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.

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.

Terminal-Fenster
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 --quiet
git -C "$old_root" diff --cached --quiet
plutil -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.

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.

Terminal-Fenster
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"

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.

Terminal-Fenster
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.

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.

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.

Wenn der neue Ort nicht funktioniert, wird der Agent erneut gestoppt, das Projekt zurückverschoben und die ursprüngliche Definition wieder registriert.

Terminal-Fenster
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 "$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.