Elastic Beanstalk, Whenever gem, and cron jobs in Ruby.

Evan Johnson
Coach Cheetah
Published in
3 min readMay 20, 2015

As your app grows in complexity, you may need to schedule reoccurring tasks. For example, on Coach Cheetah, we schedule reoccurring tasks for the following:

  • Clearing out our tmp/cache directory by running rake ‘tmp:clear’.
  • Our blog page is an RSS feed of Medium posts. We have a task that fetches new posts from that feed.
  • Calculate how much our customers are owed, and initiate payments to them.

The most common way to schedule reoccurring tasks is to use cron, which is available on most Linux systems. The problem with writing cron tasks directly is that they’re not very readable, and you have to update them every time you deploy to a new server or update your tasks. Another problem with this approach is that it moves your scheduled tasks outside of your codebase and version control.

This is where the Whenever gem comes in handy. It allows you to write verbose tasks in Ruby that can be compiled to a script that updates your crontab. To get started, you can run the following in your app’s root directory:

$ gem install whenever
$ wheneverize

This will create an initial config/schedule.rb file for you. You’ll add your reoccurring tasks in that file. I won’t go into detail about writing tasks with Whenever, but I’d recommend reading through the examples in the ReadMe file of the Whenever gem and watching the RailsCasts’ video on cron.

Once you have tasks created, you’ll need to run the following command on your server(s) to update your crontab:

$ bundle exec whenever --update-cron

While this is helpful, we don’t want to SSH to our server(s) after each deployment and run that command. Fortunately, Elastic Beanstalk (EB) allows you to write config files to place shell files in a post deployment folder. Those shell scripts are executed in alphabetical order after each deployment.

This method is somewhat risky, as an Amazon Web Services (AWS) engineer commented:

Dropping files directly into the hooks directories is risky as this is not the documented method, is different in some containers and may change in the future.

We are fine with the risk. If AWS changes the methods for customizing our EB environment, we will see errors in our log files — in which case, we can manually run the command to update our crontab for the interim.

To add this shell script to your post deployment folder, you’ll need to create a config file like the one below. It needs to live in a directory named .ebextensions, which should be located in your app’s root path (i.e. .ebextensions/01_cron.config).

https://gist.github.com/evblurbs/dbeff30b1d4664ff5a4b

Let’s review what that config file. Line 2 declares where EB will be placing our shell script. All post deployment scripts should live on your EB at:

/opt/elasticbeanstalk/hooks/appdeploy/post/

Lines 11–13 are getting EB container variables. Line 15 initiates our EB environment variables, which allows us to initiate the version of Ruby our app uses on line 16. This allows us to run bundle exec.

Line 18 changes to the app’s root directory on our EB. We then execute the Whenever command to update our crontab. Line 20 is optional and prints out the updated crontab to our logs (logs/eb-activity.log).

Deploy the new file, and you should have a post deployment script that calls the Whenever command to update your crontab. I hope you found this helpful. Feel free to post any questions, updates, or clarifications. I’ll update the post accordingly.

--

--