I found a way to do it. I added the following to the plist file.
Instead of
<key>KeepAlive</key>
<true/>
I made it
<key>KeepAlive</key>
<dict>
<key>SuccessfulExit</key>
<false/>
</dict>
Just setting KeepAlive to false would interfere with the job starting at all. (It was presumably waiting to be called by someone.) But KeepAlive's status can also be determined at runtime. This service now restarts automatically when it quits for no good reason (i.e. when it is killed) but not when it quits for a reason (i.e. was shut down regularly). This is what I need.
Update June 2020
I created a cross-platform tool to handle creating launchd
and systemd
service files:
Using launchd
launchd
can easily get into "weird" states.
load
means to read the config file and potentially schedule a launch.
unload
means to stop
and unschedule the config file
start
will start the service (ignoring the schedule, I believe)
stop
will stop the service (again, ignoring the schedule)
Generally if you want to "restart" it you unload and reload the config like this:
launchctl unload -w ~/Library/LaunchAgents/com.apple.myservice.plist
launchctl load -w ~/Library/LaunchAgents/com.apple.myservice.plist
The -w
means "write" which means that the change will affect reboots (will load every login or boot... or will not load ever again at login or boot).
If it's a system-level service (in /Library/LaunchDaemons
or /Library/LaunchAgents
you may need to do it with sudo
(and if you did it without sudo by mistake, you may need to unload it without sudo and then reload it with sudo)
The key in a file that causes it to start
on load
is RunAtLoad
(and KeepAlive
keeps it running if it dies for some reason)
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
It's sometimes tricky to get debug logging from launchctl itself, but the keys StandardErrorPath
and StandardOutPath
can at least help you know if your application is dying due to missing or bad information (an unexpanded environment variable or non-writable path, for example). Just be sure that the path you specify is writable by the user running the process.
<key>StandardErrorPath</key>
<string>/tmp/appname-error.log</string>
<key>StandardOutPath</key>
<string>/tmp/appname-info.log</string>
Because they're so hard to debug, I'd recommend using LaunchControl or launched and mix that with a healthy reading of launchd.info.
Also, there are a number of debugging hints here:
https://serverfault.com/questions/183589/how-do-i-activate-launchd-logging-on-os-x
I haven't tried it yet myself, but this solution looks the simplest:
sudo launchctl log level debug
tail -f /var/log/system.log
Best Answer
Try removing the
sudo
and just run:When attempting to unload some LaunchDaemons, it will return
"Could not find specified service"
if usingsudo
.