6

On man launchd.plist it says (emphasis mine)

StartCalendarInterval This optional key causes the job to be started every calendar interval as specified. Missing arguments are considered to be wildcard. The semantics are similar to crontab(5) in how firing dates are specified. Multiple dictionaries may be specified in an array to schedule multiple calendar intervals.

My plist file is /Users/enricozb/test.plist and contains

<?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.enricozb.test</string>
    <key>ProgramArguments</key>
    <array>
        <string>date</string>
    </array>
    <key>StandardOutPath</key>
    <string>/Users/enricozb/test.txt</string>
    <key>StartCalendarInterval</key>
    <dict>
        <key>Hour</key>
        <integer>21</integer>
    </dict>
</dict>
</plist>

Notice that Hour is set to 21, aka, 9PM. Also, notice that the command is just basically date > /Users/enricozb/test.txt. I ran

launchctl load /Users/enricozb/test.plist
launchctl start com.enricozb.test

This fires once right after the launchctl start command, and never again.

I was assuming that since the documentation says that missing arguments are wildcard, that the Minute field would be wildcard too. Why is this not running every minute?

2 Answers 2

4

Edit start

You got it all correct except for enclosing your <dict> element inside an <array> element. Your script will run every minute from 21:00 to 21:59 with the following as your StartCalendarInterval key :

    <key>StartCalendarInterval</key>
    <array>
        <dict>
            <key>Hour</key>
            <integer>21</integer>
        </dict>
    </array>

If you wanted your script to run every minute, every hour, every day, every year, the following would be the correct (but certainly not obvious) syntax for that:

    <key>StartCalendarInterval</key>
    <array>
        <dict/>
    </array>

My original answer (below) would also work, but it's clearly much more tedious! OTOH, if one needed every other minute, or certain minutes, it might be useful.

Edit end


<key>StartCalendarInterval</key>
    <array>
        <dict>
            <key>Minute</key>
            <integer>0</integer>
        </dict>
        <dict>
            <key>Minute</key>
            <integer>1</integer>
        </dict>
        <dict>
            <key>Minute</key>
            <integer>2</integer>
        </dict>
        <dict>
            <key>Minute</key>
            <integer>3</integer>
        </dict>
        <dict>
            <key>Minute</key>
            <integer>4</integer>
        </dict>

       ... ad nauseum ...

        <dict>
            <key>Minute</key>
            <integer>59</integer>
        </dict>

    </array>

To answer your question, "Why is this not running every minute?", it's only because you failed to enclose <dict> inside <array>. FWIW, it seems very odd to me also, and WHY it's designed this way is an answer I'd like to hear myself. But then I guess Apple could use the defense that "just because the semantics are similar does not mean the syntax is."

2
  • 1
    This is the syntax that I used, and I still cannot get it to work. I’ve added the full plist to my comment. What version of macOS are you using? I’m on Mojave.
    – TJ Luoma
    Commented Dec 1, 2019 at 17:27
  • 1
    macOS Catalina 10.15.6: <array> <dict/> </array> fires every minute, but <array><dict><key>Hour</key><integer>21</integer></dict></array> does not (with the right time). Specifing Minute does work again. A bunch of entries including minute keys work as well.
    – BadAtLaTeX
    Commented Nov 4, 2021 at 20:12
2

I think this is a bug in launchd.

If I take out the hour designation, it fires every minute.

But if I restrict the plist to only 9pm, then it only fires once.

Update

This is what I tried (with the hour changed to ’12’ because that’s the current hour when I tried to test it).

The ’test.txt’ file never gets created.

<?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.tjluoma.everyminute</string>
    <key>Program</key>
    <string>/bin/date</string>
    <key>StandardOutPath</key>
    <string>/Users/tjluoma/Desktop/test.txt</string>
    <key>StartCalendarInterval</key>
    <array>
        <dict>
            <key>Hour</key>
            <integer>12</integer>
        </dict>
    </array>
</dict>
</plist>

This does create/update the file every minute

<?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.tjluoma.everyminute</string>
    <key>Program</key>
    <string>/bin/date</string>
    <key>StandardOutPath</key>
    <string>/Users/tjluoma/Desktop/test.txt</string>
    <key>StartCalendarInterval</key>
    <array>
        <dict/>
    </array>
</dict>
</plist>
4
  • Not a bug... please see my (heavily) edited answer.
    – Seamus
    Commented Dec 1, 2019 at 14:14
  • Within <array> ... </array> you <dict/> and I've not seen that before, only <dict> and </dict>. What's the significance of having the / where it is in <dict/>? Commented Dec 1, 2019 at 18:34
  • 3
    <dict/> is shorthand for <dict></dict> in XML. Commented Dec 1, 2019 at 18:39
  • 1
    I should add that all of my examples from <soma-zone.com/LaunchControl>. I don’t write any of these plists myself. Life is too short and LaunchControl is too good.
    – TJ Luoma
    Commented Dec 1, 2019 at 18:48

You must log in to answer this question.

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