Replacing cron with iCal

cron is deprecated in OS X. iCal makes a straightforward, if tedious, replacement, despite its limited support for scripted alarms.

In iCal you can easily create a repeating event with an associated alarm that runs a script.

ical_repeating_event.png


Put all of your periodic system management events into a hidden "Automation" calendar (so they don't clutter up the calendar view) and you're all set.

automation_calendar.png


Of course, there's a problem. I prefer to write system management scripts using Python. iCal can run only AppleScripts.

It's easy to write an AppleScript "wrapper" which just launches a shell script, but the process involves lots of button-clicking:
  • Launch Script Editor
  • Enter do shell script "/path/to/shell/script"
  • Save the script
  • Quit Script Editor
Luckily, the osacompile command lets you do the same thing from the command line. Together with Python's pathname-manipulation facilities, osacompile makes it simple to create AppleScript wrappers for shell scripts.

Given the path to a shell script, the following Python program creates a corresponding AppleScript wrapper in the same directory:
#!/usr/bin/env python
import sys, os, subprocess, logging
def main():
    for filename in sys.argv[1:]:
        pathname = os.path.abspath(filename)
        scriptname = os.path.splitext(pathname)[0] + ".scpt"
        if os.path.exists(scriptname):
            os.remove(scriptname)
        status = subprocess.call([
            "osacompile", "-e", 'do shell script "%s"' % pathname,
            "-o", scriptname])
        if status:
            logging.error("Got status %d creating %s" % 
                          (status, scriptname))

if name == "main":
    main()