Enabling cron in OSX 10.10 Yosemite
Strangely, one of the earliest things I learned in unix computing was crontab -e
. In fact, it would not be an exaggeration to say, the reason I learned to
use vim
in the first place, was so I could fire off automated jobs in cron
while I slept (Don’t ask. Mine was a complex childhood. :-) ).
I’ve never been a fan of Apple’s launchd
replacement on the OSX operating
system.
cron
has its shortcoming to be sure, but it’s unix-y, simple, and let’s face
it… gets things done, plus, it works on millions of systems worldwide. While
I get that Apple wanted to replace the historical soup that was initd
(amongst
other things), I’ve always felt launchd
was painful. Admittedly, this might
just be because I’ve always found cron
so unbelievably fit-for-purpose when
you actually know how to use it.
Apple seems to have gone out of its way to make cron
a bit tricky for you to
enable, but after some substantial googling and experimentation, I thought I’d
write it down so you don’t have to go through the same rigmarole.
What You Don’t Get
Before you enable your crontab
though, just a few caveats on what you do get
with launchd
, just in case you’d rather use one of the GUI apps to interface
with that and solve the same problem, instead of going this route.
The main thing, is that launchd
tasks will check upon upon waking from
sleep, whether a specific tasks was scheduled to run during sleepy time ran, and
then run it if it was supposed to (note: this does not apply if the system was
off or similarly during that time, afaik)
The other thing you can do is to use launchctl
to write background tasks
that run, so you could get around things this way as well:
launchctl submit -l task1 — $HOME/bin/task1.sh foo bar
But personally, I find the XML configuration of the plists painful and a step
down from the simplicity of a crontab
. YMMV.
Enable system cron
In a nice touch though, you can get launchd
to fire up the system (root)
cron
, if you simply do this:
🚀 ~ sudo touch /etc/crontab
You probably will need to reboot in case launchd
doesn’t want to launch it,
but doing that means that launchd
will see cron and launch it on startup.
(nb: unless you really know what you’re doing do not mess with the
/etc/crontab
file. Run all your cron jobs under your user account.)
Getting cron running for users under your crontab
The easiest way after you’ve got the above goingi, is to simply create a file
called .crontab
in your home directory. Cron will automatically pick this up
for you and start running it if it’s present on startup.
The canonical way to do this is the following command:
🚀 ~ crontab -e
which will dump you into the old-school-y (yet surprisingly resurgent) editor
vim
. If you’ve never used it before, well… it may be a bit of a shock. I
certainly recommend investing the time to learn, but assuming you are in oh my
god, just tell me how to get this working! mode, type this in the command line
before executing crontab -e
🚀 ~ export EDITOR=nano
(nb: if you’re stuck in vi at the moment, hit :q!
to exit and get back to
the command line and do the above.).
Once you’re in the vi editor, it’s really just simple text editing.
For example, here’s the line I put in to do routine, weekly back ups of my Gmail using Gmail Vault (I’d recommend having the logging going in case you need to debug things.):
15 13 * * 1 /usr/local/bin/gmvault sync -t quick -d /Users/me/mail_backup_dir
me@.example.com > ~/mail_backup_dir/gmvault.log
2> ~/mail_backup_dir/gmvault-error.log
(nb: all the above should be on one line in your crontab, not split over 3)
Admittedly, you could make this shorter without the logging, but I like having that in there for checking and goof proofing. What this cron does is run the gmvault quick sync command to a specified backup directory every Monday at 1:15 pm.
Exit vim, remembering to save the file (:wq
), and then do a crontab -l
to
make sure it stuck. This should list the contents of the crontab file.
Normally, this should just work, but if it appears that cron still isn’t working
you can also give it a kick with crontab ~/.crontab
Troubleshooting
And believe it or not, you may still not be there.
Again, some little quirks with Apple’s (admittedly fabulous) OSX may be tripping you up.
If you are in vim (the default for editing on crontab -e
and do the funky
:wq
to write and quit and you get,
crontab: "/usr/bin/vi" exited with status 1
you will annoyingly find your changes have not been saved. What gives, right?
Apparently, this has to do with the way crontab wants temporary files to work
and how it names them. Suffice it to say, there are a few ways around this. The
one I added to my .vimrc
since it seemed the least intrusive was:
set backupskip=/tmp/*,/private/tmp/*`
Fire crontab -e
back up again after saving the above and any changes made to
the crontab should be saved.
An even better solution someone posted on the Vim Wikia is a lot more specific in case you don’t like the idea of the above solution.
au BufEnter /private/tmp/crontab.* setl backupcopy=yes
There are a few other ways you can accomplish the same thing, but the others involve editing in multiple places or in the bash profile and are not as clean as this one which is fairly vim specific.
Denouement
And that, is how you get cron
enabled and running on OSX Yosemite.
My cron
tasks have been chugging away quite happily over the past few weeks
and I have to admit I’m a lot happier for my OSX working the way I want. While I
realize that a number of Linux distros have also attempted to replace the
initd
startup with their solutions, Upstart being the one most recognizable,
I’m assuming cron is still the word in the Linux world. Glad to have it back on
my OSX.