Take the 2-minute tour ×
Ask Different is a question and answer site for power users of Apple hardware and software. It's 100% free, no registration required.

I have written a Ruby script that I need to run every 12 hours. Is there an easy way to do this in OS X (specifically Lion)?

share|improve this question

2 Answers 2

There are a couple of ways of doing this, but the details depend on a couple of questions: Does the script need to run as root (Admin) or a regular user? Does it need to run on any specific schedule, or just a 12-hour interval?

The OS X-ish option is to create a LaunchDaemon. Create a file named /Library/LaunchDaemons/local.scriptname.plist, with contents 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.scriptname</string>
        <key>ProgramArguments</key>
        <array>
                <string>/path/to/script</string>
                <string>someargument</string>
                <string>anotherargument</string>
        </array>
        <key>StartInterval</key>
        <integer>43200</integer>
        <key>RunAtLoad</key>
        <false/>
        <key>KeepAlive</key>
        <false/>
</dict>
</plist>

Notes: 43200 is 12 hours in seconds, meaning that this will every 12 hours starting at boot. You should replace scriptname with a more appropriate identifier in both the Label value and the filename (and if you're going to publish this, replace "local." prefix with your domain name in reverse order, e.g. "example.com.scriptname"). If it should run as someone other than root, add:

        <key>UserName</key>
        <string>usertorunas</string>

If you need it to run at particular times of day, replace the StartInterval key and value with something like this:

        <key>StartCalendarInterval</key>
        <array>
                <dict>
                        <key>Hour</key>
                        <integer>6</integer>
                        <key>Minute</key>
                        <integer>0</integer>
                </dict>
                <dict>
                        <key>Hour</key>
                        <integer>18</integer>
                        <key>Minute</key>
                        <integer>0</integer>
                </dict>
        </array>

...replacing Hours 6 and 18 (6pm) with the hours you want it to run.

The other option is to use cron, which is more generic-unix (but works fine on OS X). Use the command crontab -e to create/edit the crontab file. The crontab will be created for whichever user you create it with, so if your script should run as root, use sudo crontab -e. The crontab should look something like this:

0       6,18       *       *       *       /path/to/script someargument otherargument

Note that there's no equivalent of StartInterval here, this always runs it at 6am and 6pm.

share|improve this answer
    
LaunchDaemons are definitely the way to go on OS X. If you don't feel like messing with plist files, check out an app called Lingon: peterborgapps.com/lingon/index.html that will create them for you. –  Vickash Jul 14 '12 at 20:51
    
I tried the cron method, however it seems to not be working properly. I have a line in my script that writes the last time it ran to a text file, and the text file isn't updating at the times I specified for the script to run. –  finiteloop Jul 15 '12 at 1:41
    
I'd try logging when the script starts, and see if that's any different. Also, try adding >>/tmp/scriptname.log 2>&1 to the crontab entry, and see if anything informative shows up in that log. One possibility is that your script depends on some bit of environment (e.g. search paths) that aren't set by cron (it runs jobs in a very minimal environment, and this is a common source of trouble with them). –  Gordon Davisson Jul 15 '12 at 5:44
2  
Per-user services that don't need to be run as root are normally saved to ~/Library/LaunchAgents/. The property lists have to be loaded manually with something like launchctl load ~/Library/LaunchAgents/local.scriptname.plist or by logging out and back in. You have to unload and reload a plist to apply changes. If someone doesn't know how to use vi, you can change the EDITOR variable like EDITOR=nano crontab -e. –  ؘؘؘؘ Jul 15 '12 at 13:55
1  
And StartCalendarInterval can also be an array of more than one dictionary, so you don't need to save two separate property lists. –  ؘؘؘؘ Jul 15 '12 at 13:59

Great advice above. However, I'd have to say using cron is the best, most robust solution. Not only is it stable; it will also prepare you to work in other environments outside of OS X.

share|improve this answer
1  
cron is deprecated on Mac OS X; launched is Apple's recommended replacement. –  Graham Miln Jul 15 '12 at 18:01

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.