Skip to content

Commit 432bc2f

Browse files
chore(mdm): use launchctl bootstrap/bootout instead of load/unload
1 parent a839a7b commit 432bc2f

1 file changed

Lines changed: 22 additions & 7 deletions

File tree

internal/launchd/launchd.go

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -130,11 +130,19 @@ func Install(exec executor.Executor, log *progress.Logger) error {
130130

131131
log.Debug("launchd install: plist=%q log_dir=%q interval=%ds user_home=%q is_root=%v", plistPath, logDir, intervalSeconds, userHome, exec.IsRoot())
132132

133-
// Load plist
134-
_, _, exitCode, err := exec.Run(ctx, "launchctl", "load", plistPath)
135-
log.Debug("launchctl load %q: exit_code=%d err=%v", plistPath, exitCode, err)
133+
// Bootstrap plist into its launchd domain. Apple actively recommends
134+
// `bootstrap`/`bootout` over the older `load`/`unload` verbs, which
135+
// are on the path to deprecation. Root daemons live in the `system`
136+
// domain; user LaunchAgents in `gui/<uid>`. Available since macOS
137+
// 10.11, so every machine we target supports it.
138+
domain := "system"
139+
if !exec.IsRoot() {
140+
domain = fmt.Sprintf("gui/%d", os.Getuid())
141+
}
142+
_, _, exitCode, err := exec.Run(ctx, "launchctl", "bootstrap", domain, plistPath)
143+
log.Debug("launchctl bootstrap %q %q: exit_code=%d err=%v", domain, plistPath, exitCode, err)
136144
if err != nil || exitCode != 0 {
137-
return fmt.Errorf("failed to load launchd configuration")
145+
return fmt.Errorf("failed to bootstrap launchd configuration")
138146
}
139147

140148
log.Progress("launchd configuration completed successfully")
@@ -164,11 +172,18 @@ func doUninstall(ctx context.Context, exec executor.Executor, log *progress.Logg
164172
plistPath = agentPlistPath()
165173
}
166174

167-
// Unload
175+
// Bootout. `bootout` removes a service from its domain regardless of
176+
// how it was originally added, so it works on plists previously
177+
// `launchctl load`-ed by older agent versions during upgrade.
168178
stdout, _, _, _ := exec.Run(ctx, "launchctl", "list")
169179
if strings.Contains(stdout, label) {
170-
_, _, exitCode, err := exec.Run(ctx, "launchctl", "unload", plistPath)
171-
log.Debug("launchctl unload %q: exit_code=%d err=%v", plistPath, exitCode, err)
180+
domain := "system"
181+
if !exec.IsRoot() {
182+
domain = fmt.Sprintf("gui/%d", os.Getuid())
183+
}
184+
target := domain + "/" + label
185+
_, _, exitCode, err := exec.Run(ctx, "launchctl", "bootout", target)
186+
log.Debug("launchctl bootout %q: exit_code=%d err=%v", target, exitCode, err)
172187
log.Progress("Unloaded launchd agent")
173188
}
174189

0 commit comments

Comments
 (0)