Run an AppleScript daily with launchd

applescriptlaunchd

I'm trying to run an AppleScript which ejects all drives (from the excellent answer by Monomeeth here) daily at 8 am using launchd. After some searching, I decided the best way to do this was by using launchd. However, I'm running into an error.

The .plist which I have in my user LaunchAgents directory is as follows:

<?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>local.SkeletonBow.EjectAllDrivesAt8</string> 
  <key>Program</key> 
  <string>/usr/bin/osascript</string> 
  <key>ProgramArguments</key> 
  <array> 
    <string>/usr/local/etc/Daily\ Scripts/Eject\ All.scpt</string>
  </array> 
  <key>StartCalendarInterval</key>
  <dict>
      <key>Hour</key>
      <integer>08</integer>
      <key>Minute</key>
      <integer>00</integer>
  </dict>
</dict> 
</plist> 

The AppleScript in question, Eject All.scpt, runs fine when I run it with osascript Eject\ All.scpt in my zsh shell.

According to this site, I should "load the job" into launchctl. I did this by running, according to their instructions, the following:

launchctl load ~/Library/LaunchAgents/local.SkeletonBow.EjectAllDrivesAt8.plist

And then tried to test it by running

launchctl start local.SkeletonBow.EjectAllDrivesAt8.plist

However, this particular action causes a cross to be shown in the Terminal, implying that something wrong has happened. I'm guessing that it's due to the syntax in my .plist file.

Best Answer

One shouldn't include the .plist extension when starting a launchtl process directly. Your command should read, instead, launchctl start local.SkeletonBow.EjectAllDrivesAt8

Also, the launchctl man pages indicate one shouldn't use leading zeroes when setting Calendar start time. The content should be <integer>8</integer> and <integer>0</integer> for the Hour and Minute keys.

Keep in mind, too, that when using CalendarInterval (as opposed to an elapsed-time Interval) to set a launch time for a process, that if the machine should unexpectedly be asleep at 8:00AM and therefore be unable to initiate the process, it will initiate the process upon awakening. That does not happen when the time setting is interval based.