#164
Jun 01, 2009

Cron in Ruby

Cron is great for handling recurring tasks, but it is an external dependency with a crazy syntax. In this episode I show you how to use Whenever to create cron jobs with Ruby.
Tags: tools plugins
Download (10.3 MB, 8:13)
alternative download for iPod & Apple TV (8.7 MB, 8:13)

Resources

crontab -e
crontab -l
sudo rake gems:install
wheneverize .
whenever --update-crontab store
# config/environment.rb
config.gem 'javan-whenever', :lib => false, :source => 'http://gems.github.com'

# config/schedule.rb
every 2.hours do
  rake "thinking_sphinx:index"
end

every :reboot do
  rake "thinking_sphinx:start"
end

every :saturday, :at => "4:38am" do
  command "rm -rf #{RAILS_ROOT}/tmp/cache"
  runner "Cart.remove_abandoned"
end

# config/deploy.rb
after "deploy:symlink", "deploy:update_crontab"

namespace :deploy do
  desc "Update the crontab file"
  task :update_crontab, :roles => :db do
    run "cd #{release_path} && whenever --update-crontab #{application}"
  end
end

RSS Feed for Episode Comments 68 comments

1. Piotr Nowak Jun 01, 2009 at 00:59

Does it work on windows also ?


2. Marellana Jun 01, 2009 at 01:00

Thanks for this, very interesting and always useful


3. Ali Fakheri Jun 01, 2009 at 01:17

Estupendo, That was exactly what I needed for my project.Thank you Ryan


4. Adam Meehan Jun 01, 2009 at 01:45

Thanks for the episode.

Something that might be of interest is my cron DSL http://github.com/adzap/cronos

Its only the DSL, it doesn't actually handle the cron job management but is designed to be used in plugins/gems like whenever, craken and crontab to use a very natural syntax for defining the intervals. You can also use it in irb for cron sanity checks.


5. dani Jun 01, 2009 at 02:07

awesome as always! thanks again!!


6. TJ Koblentz Jun 01, 2009 at 02:09

Thank you so much for all your excellent screencasts, Ryan.

I'm an 18 year old college student suddenly getting interested in RoR and find each of your tutorials very well drawn out and ridiculously clearly explained.

I appreciate your work, thanks again!


7. Joshua Jun 01, 2009 at 02:30

Great plugin, I only started using this a couple of days ago so am surprised to see a screencast on it :)

The only problem is on the server I was using this syntax gave an invalid cronjob:

every :saturday, :at => "4:38am"


8. Raghuonrails Jun 01, 2009 at 02:45

Cool plugin tutorial + screencast...Thanks!!!


9. Javan Jun 01, 2009 at 04:02

I'm honored!


10. Javan Jun 01, 2009 at 04:08

@Joshua feel free to create an issue on github if you're having trouble. You can view your whenever generated cron jobs without actually updating your crontab by running `whenever` from the command line.


11. grosser Jun 01, 2009 at 04:10

We use a nigthly rake task that then runs everything that needs to be done, which keeps all code in ruby and nobody has to even touch the crontab

http://pragmatig.wordpress.com/2008/12/14/no-more-crontab-madness-with-a-single-night-rake-task/


12. davide Jun 01, 2009 at 05:00

another great background-task gem is http://rufus.rubyforge.org/rufus-scheduler/

i use it to run a rake task every 15 minutes, but without cron, so it works on my windows developer machine as well


13. Michael Jun 01, 2009 at 05:30

Wow! This is GREAT!

Thanks for the screencast, this is a VERY useful gem!


14. JackVandaL Jun 01, 2009 at 07:54

So no one has really answered Piotr. Does this only work on Unix machines? davide's comment seems to suggest so.


15. Ryan Bates Jun 01, 2009 at 08:28

@Piotr, AFAIK windows doesn't have cron so I'm assuming this will not work there.

However, the cron job should only be generated on your production machine. So if you are using Windows in development and Unix in production, then yes, you can use this.


16. justin Jun 01, 2009 at 08:30

crontab only works on unix machines, therefore whenever will only work on unix machines


17. The Ultimation Jun 01, 2009 at 09:05

Nice, a couple months ago I tried to find a cron solution with rails and it was really frustrating. Tried backgroundrb and a few other things to no avail. I plan on trying this asap!


18. Abdullah Jibaly Jun 01, 2009 at 10:27

Great plugin! Just wish I'd known about this a couple weeks ago when I needed it :)


19. Eric Jun 01, 2009 at 11:31

Awesome, awesome, awesome!

Ryan, you read my mind. I have been using launchd on my OSX server, but it was a bear to setup, and I was just looking into cron in anticipation of moving to an Ubuntu server. This makes my life so much easier.

Thanks :) And kudos to Javan for a fabulous gem.


20. Lourdes Jun 01, 2009 at 14:20

Does anyone have any suggestions on how to test this on a local machine first before putting it on a server? I'm having trouble figuring out how to do that. Thanks!


21. Francis Jun 01, 2009 at 18:18

How do you handle the case where things should only happen once, but if you have multiple webservers, every webserver will run the same cron action.

Eg: Cart.remove_abandoned

You probably only want this to be call once only, but if deployed on N number of webserver environment it will run N times?

Thanks!


22. Melvin Ram Jun 02, 2009 at 00:46

How does this compare to backgroundrb? It seems cleaner & will probably use less memory... but are their any down sides to this approach? Do I loose any features?


23. Javan Jun 02, 2009 at 00:53

@Lourdes You can view the cron output without actually updating your crontab by running `whenever` with no options locally (or on your server).

@Francis That's where the :roles => :db comes into play in the included capistrano task. By default the cron jobs get deployed to the db server, but you could customize this however you like, and could conceivably deploy different cron jobs to servers with different roles.

@Melvin Ram The nice thing about cron is you don't have to worry about a process dying.


24. Bill Jun 02, 2009 at 04:18

Ryan, you stated that the cron should only be generated on the production server, but what if you have a test or qa environment. You would want it setup there, but the generated cron entries have "RAILS_ENV=production". Is there a way to set that?


25. Javan Jun 02, 2009 at 04:34

@Bill A new version of the Whenever gem was just published that allows you to override variables on the fly. So when deploying to qa server you might do something like:

whenever --update-crontab my_app --set environment=qa


26. Vinay Jun 02, 2009 at 05:18

@javan/ryanb,

I wrote a simple runner task in scheduler.rb. When I entered 'whenever' in Terminal to see the cron jobs, I got the following error..
rubygems.rb:147:in `activate': can't activate activesupport (= 2.1.0, runtime), already activated activesupport-2.2.2 (Gem::Exception)

I was using daemons before this to perform some tasks relating to my app models. i could specify activesupport version to use in daemons. How can i do this here?


27. Javan Jun 02, 2009 at 05:28

@Vinay there's an open issue on github for this exact problem. I haven't had a chance to fix it, but the easy solution is to just uninstall one of your activesupport gem versions.


28. Jose Jun 02, 2009 at 07:53

Compared to many syntaxes, cron's is very predictable and comprehensible. It's no crazier than regular expressions and anyone who understands it has my respect.

In defense of cron, I'd say it keeps your system tasks in one central location rather distributed among separate applications.


29. Sam Millar Jun 02, 2009 at 08:26

This is perfect, just what I need in the App I'm currently developing!


30. Chris Johnston Jun 02, 2009 at 10:38

Very cool tool, except I can't get it to work and I can't find any support forums for it either.

When I try to run the whenever command on my production box I get the following error, any ideas?

can't activate activesupport (= 2.2.2, runtime), already activated activesupport-2.3.2


31. Nico Jun 02, 2009 at 12:12

Hey,

I've got a little detail question: what theme do you use for Textmate? Because I realy like yours, but just can't find it on the web.

Thanks,
Nico


32. Ruslan Jun 02, 2009 at 14:05

0,2,4,6.. looks ugly.
*/2 is better


33. Javan Jun 02, 2009 at 14:59

@Ruslan The */2 style syntax is less compatible across unix systems, but thanks for sharing.


34. Bill Stavroulakis Jun 02, 2009 at 17:27

What about rails applications that are written in version 1.2.6? What gem do you suggest? Because javan-whenever supports only rails >= 2.1


35. John Dewey Jun 02, 2009 at 17:56

Giving some love to craken as well:
http://github.com/latimes/craken/tree/master


36. Steven Soroka Jun 02, 2009 at 19:01

The big problem with the cron/rake pattern is that it loads the environment every time it needs to run a task.

The scheduler_daemon plugin is a much cleaner solution.

Check it out: http://github.com/ssoroka/scheduler_daemon


37. RailsCasts Fan Jun 02, 2009 at 22:44

Thanks Ryan for this new screencast ! :)
@Nico: for the TextMate theme used, check http://railscasts.com/about > "TextMate Theme" section. ;)


38. zZzZ Jun 03, 2009 at 13:14

@Piotr Nowak: AFAIK there is no such thing as cron in Windows, so nope - it works only on various Unixes: Linux, *BSD and so on...


39. Bharat Jun 06, 2009 at 10:52

Ron Bates and Javan Rock!


40. JoshL Jun 07, 2009 at 10:59

Ryan-

I've now watched this and your cast on the daemon gem and I'm confused on what you feel to be the best practice.

Let's say you need to set something up to basically continually poll your database to see if their are any new emails to deliver, or whatever. Would you use a cron job or would you use a daemon? Would you actually run it from the job or would you hand it off to something like BJ to run so the scheduler can continue? What if you have a variety of things that need to be checked, like checking for new mail from a server every 10 minutes, sending alerts every 2 minutes, pulling data from a web service every 5 minutes, etc.

I can't seem to find anything that addresses the best practice for something like this in rails.


41. Pratik Jun 07, 2009 at 12:27

Hi Ryan,

Thank you very much for these great screencasts!
Can you suggest something on the reserved words in rails? I know that this post is not relevant here, but i did not know where to. Am developing an application and already i find that i cannot use many of the words (eg: module, type, etc)

Thanks!


42. Leo Huang Jun 07, 2009 at 19:40

Thanks Ryan!
Your screen cast is the best! I always find very useful tips from your casts.


43. Gordon Isnor Jun 07, 2009 at 23:54

Great video as always.

I'm having trouble getting the crontab to write the crontab with a Capistrano deploy to EC2. While it's deploying it tells me that the crontab has been written, but when I log in and run crontab -it's still the old crontab (previous Capistrano release). I have to then manually run whenever --write-crontab. And then running crontab -l shows the correct release.

Does anybody have any ideas on what could be causing this? I have tried a million variations and nothing seems to be working.


44. Michael Jun 08, 2009 at 06:11

This is great! I've, up until now never really had the need to use repeating background processes, however, I was, just for fun, looking to see if anything existed for when I really needed it. (which I do with a lot of Rails stuff!). Sadly, I was unable to find anything for months, and then this screencast comes out. With a gem that allows you to write "Ruby" syntax to create "cronjobs"? Excellent! Being able to do that kind of important processing with such an easy syntax is extremely useful and saves a load of time, not to mention that it saves a lot of hassle for every deployment and/or server transfer. Also the fact that the server triggers it every time means that it's actually very light-weight compared to (which I never got working properly), other daemon-like gems!

Thanks Javan! I'll be watching you on Github! :)


45. shettigar Jun 12, 2009 at 11:03

Great! This is the kind of gem i was looking for 2-3 months ago. With this gem I can now configure crontab using capistrano script. Thanks!


46. Pashunya Jun 13, 2009 at 01:56

Big thanks!


47. Raimond Garcia Jun 29, 2009 at 11:30

I had a small issue when indexing from the cron job, it wouldn't reindex new records, but it worked fine when manually running the command that was in the cron file.

The solution was to add the location of the sphinx binaries to sphinx.yml (this only applies to passenger apps) http://freelancing-god.github.com/ts/en/common_issues.html.

Hope I save someone a couple of hours :)


48. Sean Kibler Jun 30, 2009 at 13:17

Although Windows does not have Cron one might have some luck using Vixie cron which can be installed in Cygwin. I have had partial success using Vixie cron on a Windows system thought it wasn't a breeze.

http://www.cygwin.com/


49. Timanya Jul 01, 2009 at 06:44

Great video as always.

I'm having trouble getting the crontab to write the crontab with a Capistrano deploy to EC2. While it's deploying it tells me that the crontab has been written, but when I log in and run crontab -it's still the old crontab (previous Capistrano release). I have to then manually run whenever --write-crontab. And then running crontab -l shows the correct release.

Does anybody have any ideas on what could be causing this? I have tried a million variations and nothing seems to be working.


50. Lyudmilich Jul 04, 2009 at 02:47

Nice, thx.


51. Peter Haza Jul 09, 2009 at 05:41

Is this better than using a daemon, or just an alternative? And does this create a crontab conflict if you have several apps using the same gem?


52. Andy Ferra Jul 12, 2009 at 21:21

If you find that your scheduled thinking sphinx task is running but your index isn't updating then you probably need to add PATH and possibly SHELL variables to the top of your crontab file because cron doesn't load your users ennvironment.


53. fanparty Jul 19, 2009 at 06:24

Cron is not so hard to understand, but with such plug-in it became easier to use!


54. Anatoly Sep 08, 2009 at 03:43

Very useful episode, thanks!


55. Jimmy Sep 11, 2009 at 15:01

I've been using this for a while and it's great. Timezone support would make it fantastic!


56. top oyunları Oct 22, 2009 at 03:21

perfect share


57. Emil Kampp Nov 25, 2009 at 06:47

Hi there.

I'm using nifty-config and the whenever gem. But the values set in app_config.yml are not recognized when running the "whenever --update-crontab" command.

How do I fix this? Any suggestions?


58. Luci Nov 25, 2009 at 19:34

hi everyone,

I have a question about cron in ruby. At the same time rails can running multi threads( requests). Example:

30 * * * * rake RAILS_ENV=production schedule:reload_30minutes

5 * * * * rake RAILS_ENV=production schedule:reload_5minutes

How do it?
(thanks)


59. thenetduck Dec 13, 2009 at 17:56

Hi,
I noticed in the source line that you were using the gems.github.com and on their wiki at github their using gemcutter. Which one should I use? Is gemcutter the most recent?

Thanks


60. 3d oyunlar Dec 28, 2009 at 06:49

thanks your share i love this article


61. Walter Schreppers Jan 22, 2010 at 08:43

I like wheneverize. Problem I bumped into today. It allows only one crontab per user. So if you have 2 apps running they need to be with different user accouns otherwise wheneverize deletes the crontab settings from the other running app?! This seems unnecessary. Maybe the rails app name could be used to differentiate the 2 crontab lists? Does backgroundrb allow for several crons running on same user?
(Might save me some time looking for another suited plugin...)


62. gordon yeong Feb 11, 2010 at 17:01

ryan,
 the video's sweet and it's convinced me to try out whenever on my ubuntu 8.04 hardy server.

Nevertheless, it's not so sweet now cause I cannot run "whenever".

 Anyway, I installed the gem using sudo and the installation went well.

Now , when I run "whenever", this is what I got.
barney_dinasour@evolutionct9a:~/projects/myApp$ whenever
/usr/local/lib/ruby/gems/1.8/gems/whenever-0.4.1/lib/whenever/
job_list.rb:20:in `initialize': /usr/local/lib/ruby/gems/1.8/gems/
activesupport-2.3.5/lib/active_support/dependencies.rb:105:in
`const_missing': uninitialized constant Whenever::JobList::RAILS_ROOT
(NameError)
  from (eval):12:in `initialize'
  from /usr/local/lib/ruby/gems/1.8/gems/whenever-0.4.1/lib/whenever/
job_list.rb:37:in `every'
  from (eval):11:in `initialize'
  from /usr/local/lib/ruby/gems/1.8/gems/whenever-0.4.1/lib/whenever/
base.rb:4:in `eval'
  from /usr/local/lib/ruby/gems/1.8/gems/whenever-0.4.1/lib/whenever/
job_list.rb:20:in `initialize'
  from /usr/local/lib/ruby/gems/1.8/gems/whenever-0.4.1/lib/whenever/
base.rb:4:in `new'
  from /usr/local/lib/ruby/gems/1.8/gems/whenever-0.4.1/lib/whenever/
base.rb:4:in `cron'
  from /usr/local/lib/ruby/gems/1.8/gems/whenever-0.4.1/lib/whenever/
command_line.rb:31:in `run'
  from /usr/local/lib/ruby/gems/1.8/gems/whenever-0.4.1/lib/whenever/
command_line.rb:5:in `execute'
  from /usr/local/lib/ruby/gems/1.8/gems/whenever-0.4.1/bin/whenever:
30
  from /usr/local/bin/whenever:19:in `load'
  from /usr/local/bin/whenever:19
barney_dinasour@evolutionct9a:~/projects/myApp$

My configuration:
----------------------
* gem version is 1.3.5
* rails 2.3.5
* Ubuntu Hardy 8.04

Can anyone please help? :) thanks


63. Gordon Feb 11, 2010 at 19:54

ryan,
 the video's sweet and it's convinced me to try out whenever on my ubuntu 8.04 hardy server.

 Anyway, I installed the gem using sudo and the installation went well.

Nevertheless, it's not so sweet now as the 3rd cron entry to remove items off the app's tmp/cache doesn't work.
It's got some issues with RAILS_ROOT not being set despite the fact that I have even set the path
(ie set :path, "<location of my app>").

Now , when I run "whenever", this is what I got.
barney_dinasour@evolutionct9a:~/projects/myApp$ whenever
/usr/local/lib/ruby/gems/1.8/gems/whenever-0.4.1/lib/whenever/
job_list.rb:20:in `initialize': /usr/local/lib/ruby/gems/1.8/gems/
activesupport-2.3.5/lib/active_support/dependencies.rb:105:in
`const_missing': uninitialized constant Whenever::JobList::RAILS_ROOT
(NameError)
  from (eval):12:in `initialize'
  from /usr/local/lib/ruby/gems/1.8/gems/whenever-0.4.1/lib/whenever/
job_list.rb:37:in `every'
  from (eval):11:in `initialize'
  from /usr/local/lib/ruby/gems/1.8/gems/whenever-0.4.1/lib/whenever/
base.rb:4:in `eval'
  from /usr/local/lib/ruby/gems/1.8/gems/whenever-0.4.1/lib/whenever/
job_list.rb:20:in `initialize'
  from /usr/local/lib/ruby/gems/1.8/gems/whenever-0.4.1/lib/whenever/
base.rb:4:in `new'
  from /usr/local/lib/ruby/gems/1.8/gems/whenever-0.4.1/lib/whenever/
base.rb:4:in `cron'
  from /usr/local/lib/ruby/gems/1.8/gems/whenever-0.4.1/lib/whenever/
command_line.rb:31:in `run'
  from /usr/local/lib/ruby/gems/1.8/gems/whenever-0.4.1/lib/whenever/
command_line.rb:5:in `execute'
  from /usr/local/lib/ruby/gems/1.8/gems/whenever-0.4.1/bin/whenever:
30
  from /usr/local/bin/whenever:19:in `load'
  from /usr/local/bin/whenever:19
barney_dinasour@evolutionct9a:~/projects/myApp$

My configuration:
----------------------
* gem version is 1.3.5
* rails 2.3.5
* Ubuntu Hardy 8.04

Can anyone please help? :) thanks


64. sedo Mar 06, 2010 at 03:37

i love it thank you.


65. giydirme oyunları Apr 20, 2010 at 06:42

giydirme oyunları, kızgiydirmeoyunları, giydirme


66. giydirme oyunlari Jun 30, 2010 at 13:00

Very nice site and article..


67. mario oyunu Jun 30, 2010 at 13:01

Great.I like it!


68. mario oyunları Jun 30, 2010 at 13:03

Thank you,I think it's very useful.


69. giydirme oyunları Jun 30, 2010 at 13:13

good idea,i like it


70. Predictii Hochei Jul 19, 2010 at 07:02

Thanks for this post.


71. flowers Jul 23, 2010 at 23:18

Really like this website, this really helps and very useful.
I love flowers...I am also interested to send flowers all over the world....


72. tschundeee Jul 28, 2010 at 07:40

Thx Ryan for another nice screencast.
I can only recommend using http://rufus.rubyforge.org/rufus-scheduler/

This has by far the best integration into rails that I know...


73. pll fm transmitter Aug 04, 2010 at 20:15

So no one has really answered Piotr. Does this only work on Unix machines? davide's comment seems to suggest so.


74. free directory list Aug 11, 2010 at 22:35

Thanks for the help.


75. get diploma Aug 16, 2010 at 00:30

Very good information .... Thanks guy...


76. Lovemore Aug 20, 2010 at 03:42

Hi Guys

Can i use whenever to pull a list of all crontab entries on multiple server to a file/database???? i just need to maintain a list of all the crontab entries on my linux/unix servers.


77. Wholesale baseball hats Aug 20, 2010 at 20:33

Fantastic Read! Looking forward to more! Bookmarked the site and will be back again!


78. Air Jordan Force 4 Aug 23, 2010 at 23:15

I came to your article from another article and am really interested in this learning about this. , I feel strongly about information and love learning more on this. Thanks for this great post. I have become a huge fan of this website and I really cant wait to read you next posts!


79. Wholesale Electronics Aug 25, 2010 at 01:57

Discount Wholesale Electronics, Wholesale Cell Phones, Electronic Gadgets and More from the Best Dropship Wholesaler


80. louis vuitton shoes Aug 26, 2010 at 23:22

Thanks for sharing your article. I really enjoyed it. I put a link to my site to here so other people can read it. My readers have about the same interets


81. oyun1 Aug 29, 2010 at 03:51

thank you


82. Avatar oyunları Aug 29, 2010 at 03:53

thank you.


83. mario oyunları Aug 29, 2010 at 17:32

Pretty good list, I’m just glad it’s concise.


84. GSM Cell Phones Aug 30, 2010 at 20:12

thanks for your sharing this post, i like it so much.


85. snow boots Aug 30, 2010 at 20:59

Awesome, awesome, awesome!

Ryan, you read my mind. I have been using launchd on my OSX server, but it was a bear to setup, and I was just looking into cron in anticipation of moving to an Ubuntu server. This makes my life so much easier.

Thanks :) And kudos to Javan for a fabulous gem.


86. louis vuitton sunglasses Sep 01, 2010 at 21:37

Very good post. Made me realize I was totally wrong about this issue. I figure that one learns something new everyday. Mrs Right learned her lesson! Nice, informative website by the way.

Add your comment:

(SKIP THIS ONE)

(required)

(not shown)


(use pastie or gist for code)

sponsored by:
if you want to help:
required:
Get Quicktime Player
Give Back to Open Source