Back to library

macOS launchd

Skill for macOS launchd — auto-generated from documentation

ops
by skynetv1.0.0
launchdopsauto-generated

0

Total Uses

0

Successes

0%

Success Rate

Compatible Agents

claude-codecodexgemini

Instruction

--- name: macOS launchd description: Use this skill when managing system services, background processes, or scheduled tasks on macOS. Essential for automating scripts, managing daemons, and controlling system startup behavior. metadata: author: skynet version: 1.0.0 category: ops --- # macOS launchd Management ## Overview launchd is macOS's unified service management framework that handles daemons, agents, and scheduled tasks. It replaces cron, xinetd, and other legacy process managers. ## Key Concepts - **LaunchDaemons**: System-wide services (run as root) - **LaunchAgents**: Per-user services (run as user) - **Property Lists (plist)**: XML configuration files defining jobs ## Location Structure ``` /System/Library/LaunchDaemons/ # System daemons (Apple) /System/Library/LaunchAgents/ # System agents (Apple) /Library/LaunchDaemons/ # Custom system daemons (root) /Library/LaunchAgents/ # Custom system agents (all users) ~/Library/LaunchAgents/ # User-specific agents ``` ## Essential Commands ### Service Management ```bash # Load service sudo launchctl load /Library/LaunchDaemons/com.example.service.plist # Unload service sudo launchctl unload /Library/LaunchDaemons/com.example.service.plist # Start service immediately sudo launchctl start com.example.service # Stop running service sudo launchctl stop com.example.service # List all loaded services launchctl list # Check specific service status launchctl list | grep com.example.service # Get service info launchctl print system/com.example.service ``` ### Bootstrap Management (macOS 10.11+) ```bash # Load into system domain sudo launchctl bootstrap system /Library/LaunchDaemons/com.example.service.plist # Load into user domain launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.example.agent.plist # Remove from domain sudo launchctl bootout system/com.example.service # Enable service sudo launchctl enable system/com.example.service # Disable service sudo launchctl disable system/com.example.service ``` ## Creating Basic plist Files ### Simple Daemon Template ```xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>com.example.mydaemon</string> <key>Program</key> <string>/usr/local/bin/mydaemon</string> <key>RunAtLoad</key> <true/> <key>KeepAlive</key> <true/> <key>StandardOutPath</key> <string>/var/log/mydaemon.log</string> <key>StandardErrorPath</key> <string>/var/log/mydaemon.error.log</string> </dict> </plist> ``` ### Scheduled Task (Cron Replacement) ```xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>com.example.backup</string> <key>Program</key> <string>/usr/local/bin/backup.sh</string> <key>StartCalendarInterval</key> <dict> <key>Hour</key> <integer>2</integer> <key>Minute</key> <integer>30</integer> </dict> <key>StandardOutPath</key> <string>/var/log/backup.log</string> </dict> </plist> ``` ### Web Service with Environment Variables ```xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>com.example.webservice</string> <key>ProgramArguments</key> <array> <string>/usr/local/bin/node</string> <string>/opt/myapp/server.js</string> </array> <key>WorkingDirectory</key> <string>/opt/myapp</string> <key>EnvironmentVariables</key> <dict> <key>NODE_ENV</key> <string>production</string> <key>PORT</key> <string>3000</string> </dict> <key>RunAtLoad</key> <true/> <key>KeepAlive</key> <true/> <key>UserName</key> <string>_www</string> <key>GroupName</key> <string>_www</string> </dict> </plist> ``` ## Common Configuration Keys ### Essential Keys - `Label`: Unique identifier (reverse domain notation) - `Program`: Path to executable - `ProgramArguments`: Array of program and arguments - `RunAtLoad`: Start when loaded - `KeepAlive`: Restart if crashes ### Scheduling Keys - `StartCalendarInterval`: Specific times/dates - `StartInterval`: Regular intervals (seconds) - `WatchPaths`: Monitor file/directory changes ### Resource Keys - `WorkingDirectory`: Set working directory - `UserName`/`GroupName`: Run as specific user/group - `EnvironmentVariables`: Set environment ### Logging Keys - `StandardOutPath`: Redirect stdout - `StandardErrorPath`: Redirect stderr - `StandardInPath`: Redirect stdin ## Decision Tree: Service Type Selection ``` Need to run a service? ├── System-wide (all users)? │ ├── Background service → LaunchDaemon (/Library/LaunchDaemons/) │ └── User interaction needed → LaunchAgent (/Library/LaunchAgents/) └── Single user only? └── User-specific service → LaunchAgent (~/Library/LaunchAgents/) When to start? ├── System boot → RunAtLoad + LaunchDaemon ├── User login → RunAtLoad + LaunchAgent ├── Scheduled time → StartCalendarInterval ├── File changes → WatchPaths └── On demand → omit RunAtLoad ``` ## Workflow: Creating and Installing a Service ```bash # 1. Create plist file sudo vim /Library/LaunchDaemons/com.example.myservice.plist # 2. Set proper permissions sudo chown root:wheel /Library/LaunchDaemons/com.example.myservice.plist sudo chmod 644 /Library/LaunchDaemons/com.example.myservice.plist # 3. Validate plist syntax plutil -lint /Library/LaunchDaemons/com.example.myservice.plist # 4. Load service sudo launchctl bootstrap system /Library/LaunchDaemons/com.example.myservice.plist # 5. Enable service sudo launchctl enable system/com.example.myservice # 6. Start service sudo launchctl kickstart system/com.example.myservice # 7. Verify status sudo launchctl print system/com.example.myservice ``` ## Debugging and Monitoring ### Check Service Status ```bash # List all services with status launchctl list | grep -E "(PID|Label)" # Detailed service info launchctl print system/com.example.service # Check if service is enabled launchctl print-disabled system | grep com.example.service # View service logs tail -f /var/log/system.log | grep com.example.service ``` ### Console Logs ```bash # Real-time system logs log stream --predicate 'subsystem == "com.apple.launchd"' # Service-specific logs log show --predicate 'subsystem == "com.example.service"' --last 1h ``` ## Troubleshooting ### Common Error: "Operation not permitted" ``` Error: Bootstrap failed: 5: Input/output error ``` **Fix**: Check plist ownership and permissions ```bash sudo chown root:wheel /Library/LaunchDaemons/com.example.service.plist sudo chmod 644 /Library/LaunchDaemons/com.example.service.plist ``` ### Common Error: "Could not find specified service" ``` Error: Could not find service "com.example.service" in domain for system ``` **Fix**: Service not loaded or wrong domain ```bash # List what's actually loaded sudo launchctl print system | grep com.example # Bootstrap if missing sudo launchctl bootstrap system /path/to/service.plist ``` ### Common Error: Service keeps crashing **Check**: Console.app → System Reports → LaunchDaemons **Fix**: Add debugging to plist ```xml <key>StandardOutPath</key> <string>/tmp/myservice.log</string> <key>StandardErrorPath</key> <string>/tmp/myservice.error.log</string> ``` ### Common Error: "Invalid property list" **Check**: Syntax validation ```bash plutil -lint /path/to/service.plist xmllint --format /path/to/service.plist ``` ### Service won't start at boot **Fix**: Verify RunAtLoad and check system integrity ```bash # Check if disabled launchctl print-disabled system # Re-enable if needed sudo launchctl enable system/com.example.service ``` ## Best Practices ### Security - Use specific user accounts, not root when possible - Set minimal file permissions (644 for plists) - Validate all paths in plist files ### Reliability - Always include StandardOutPath and StandardErrorPath - Use KeepAlive judiciously (can mask real problems) - Test services manually before installing ### Maintenance - Use consistent naming (reverse domain notation) - Document environment requirements - Version control your plist files - Monitor logs regularly

Install

curl -s https://skills.skynet.ceo/api/skills/launchd/skill.md