3

I have a launchd plist in ~/Library/LaunchAgents designed to run a script located at ~/writout.sh every day at 10:30AM:

<?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.jackson.testwrite.plist</string>
    <key>Program</key>
    <string>/Users/jacksonkearl/writeout.sh</string>
    <key>StartCalendarInterval</key>
    <dict>
        <key>Hour</key>
        <integer>10</integer>
        <key>Minute</key>
        <integer>30</integer>
    </dict>
</dict>
</plist>

The script is:

#!/bin/bash
echo "it works" >> log.txt

However, nothing gets written at the desired time.

Are there steps I must take to alert launchd to the new agent? Or how else do i make the process start?

4 Answers 4

3

You need to load the launch agent into launchd.

  1. Open Terminal
  2. Type cd ~/Library/LaunchAgents
  3. Type launchctl load -w local.jackson.testwrite.plist (assuming that is the name of your plist file)

This will load and persistently enable your plist. You can check if it is loaded with launchctl list

6

To debug this, you will want to enable redirection.

<key>StandardErrorPath</key>
<string>/tmp/local.job.err</string>
<key>StandardOutPath</key>
<string>/tmp/local.job.out</string>

I also placed my version of your script in /usr/local/bin and made sure it was executable with chmod a+x

The error I get is:

/usr/local/bin/writeout.sh: line 3: log.txt: Permission denied

So, you might want to send your echo command to $TMPDIR or another place that's writeable. It looks like the default path for launchd isn't one a user can write to (and probably for good reason).

But, doing launchd/launchctl by hand is rough. I highly, highly recommend using a tool like LaunchControl or Lingon. They provide the help and automation that makes me so much better at these scripts.

Using Launch Control - it quickly let me recreate your job, had all sorts of helpful hints, and most importantly knew to suggest redirection to debug the script exit / error condition.

enter image description here

With one click, it added the lines above to my plist file and offered to save it and reload the job for me.

3

You have several errors in your plist file:

<key>Label</key>
<string>local.jackson.testwrite.plist</string>

becomes

<key>Label</key>
<string>local.jackson.testwrite</string>

and the plist is missing a

</plist>

at the end. The plist should finally look like this:

<?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.jackson.testwrite</string>
    <key>Program</key>
    <string>/Users/jacksonkearl/writeout.sh</string>
    <key>StartCalendarInterval</key>
    <dict>
        <key>Hour</key>
        <integer>10</integer>
        <key>Minute</key>
        <integer>30</integer>
    </dict>
</dict>
</plist>

To load the LaunchAgent enter:

launchctl load /Users/jacksonkearl/Library/LaunchAgents/local.jackson.testwrite.plist

To load the LaunchAgent permanently enter

launchctl load -w /Users/jacksonkearl/Library/LaunchAgents/local.jackson.testwrite.plist
0

You cannot execute something from launchd that could be edited by any yahoo. This is an important security concern!

This generally means your script has permissions like 'r_xr_xr_x' — readable and executable by anyone, but writable by no one.

Not only that, but the directory your executable lives in must not be writable by any yahoo. So you need similar permissions (unwritable by anyone) there.

I think root is an exception. So if your executable and/or directory are owned by root, the permissions can be 'rwxr_xr_x', for example.

Note that this conflicts with your script, which will try to write into the directory from which it was launched. I suspect that may be root ("/") for launchd. You should generally fully qualify file locations in such scripts.

It seems like that requirement bites me in the butt every time I mess with LaunchDaemons! It often shows up in /var/log/system.log as an error NOSYS (78), 'Function not implemented', as if that explained anything!

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .