Search code examples
macososx-maverickslaunchdlaunch-daemon

Launchd runs with manual "launchctl start", but not on StartCalendarInterval


I have a very simple Launch Daemon, com.daily.vocab.plist, which simply runs a basic script. It is supposed to run every day at a certain time (using StartCalendarInterval), but I can't get that to happen. Many posts online are saying it runs a minute or two off, but for me it just never runs.

I have been setting the run time to be 5 minutes in the future while I am testing, and now have it set to run at the 0th second of every minute, just so I can get it to work. Once it's working, I will set it to my desired daily run time.

As advised in this tutorial, it is saved in /Library/LaunchDaemons. I loaded it manually with launchctl load /Library/LaunchDaemons/com.daily.vocab.plist. I do in fact see it has loaded when I run launchctl list. When I manually tell it to run with launchctl start com.daily.vocab, it works immediately as expected. The only issue is that the StartCalendarInterval seems to be ignored. I am on Mavericks on my Macbook.

Here is the file: com.daily.vocab.plist

<?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.daily.vocab</string>
    <key>Program</key>
      <string>/Users/MGS/developer/projects/vocab-sms/scripts/DEvocab.sh</string>
    <key>StartCalendarInterval</key>
      <dict>
        <key>Second</key>
            <integer>0</integer>
      </dict>
  </dict>
</plist>

Ideally, I believe I want it to run at 7:15am every day making the StartCalendarInterval section be instead:

<key>StartCalendarInterval</key>
    <dict>
      <key>Hour</key>
        <integer>7</integer>
      <key>Minute</key>
        <integer>15</integer>
    </dict>

If you could even share an example of a LaunchDaemon you got to work using StartCalendarInterval and every step you made to make it work (e.g. running launchctl load x.x.x.plist), that would be really helpful!

Solution: This local daemon should actually be a user agent, so it needed to be saved in and loaded from the ~/Library/LaunchAgents directory. From there, I also needed to unload the agent and reload the agent.

NOTE: Daemons/Agents do not automatically update in launchd until you unload/load. You can't just save the updated .plist and expect it to work!


Solution

  • launchd plists saved in /Library/... are daemons / agents in the local domain and have to be loaded with sudo. Without sudo you're loading the daemon in the user domain which doesn't match the actual path.

    Since you are calling a script in the user domain anyway, save the script in ~/Library/LaunchAgents (it's not a daemon). The plist syntax is supposed to be correct.