Cron jobs with Ruby using RVM

Recently, I needed to setup a cron job to regularly add a job to a worker queue. I wanted to write in Ruby rather than the usual Bash in order to leverage a gem that could easily connect to the queue. I ran into a couple of issues but once I got it figured out, I gotta say, writing crons in Ruby instead of Bash is waaaaay better.

Installing RVM

I won't go into detail about this. I use RVM to manage my Ruby. Some people I know aren't too fond of it, but to each his own. Just follow these instructions:

The problem...

You want to run a ruby script you wrote as a cron job. Sounds easy enough, I usually run this from the command line:

# ruby /my/awesome/script.rb

So I can just add that to my crontab and it'll be awesome:

*/30 * * * * ruby /path/to/my/script.rb

Nope, cause now in your cron logs you're going to see:

`require': cannot load such file -- some_gem_i_need (LoadError)

Dammit! So turns out my bash profile doesn't get loaded into your cron environment. So you have to make sure that's all loaded in before these scripts will work. Which can be a bit of a nightmare because running and debugging crons is tough. You have to make an edit, install a cron, check the logs and repeat. Ugh. Or you could...

Let RVM setup your cron environment for you

Whaaa? Yeah. This, IMHO, is kinda freakin' awesome. It took my getting almost the entire environment setup before I found out this was a thing. Could have saved me a lot of time, so hopefully it will save someone reading this before bashing their heads in getting cron to run with the correct Ruby environment:

# rvm cron setup

Boom! That will actually setup a new crontab for your user with all the goodies at the top:

#sm start rvm
#sm end rvm
# Edit this file to introduce tasks to be run by cron.
# Your cron stuff down here

This basically ensures that you're running the Ruby script with the version you want and sets access to all your gems - if you need any. So now instead of writing your cron like this:

*/30 * * * * FIRST_VAR=this SECOND_VAR=that PATH=/this/crazy/path OTHER_INCLUDE_PATH="blah blah blah" MORE_HORRIBLE_ENV_VARS=true /path/to/my/script blah blah...

You can just write:

*/30 * * * * ruby /path/to/my/script.rb

Way cleaner and nicer and in in Ruby. Yay!


comments powered by Disqus