Crontab grows larger and larger with every new cleanup/maintence task…
... 0 0 1 * * cd ~/apps/my_app/current && RAILS_ENV=production rake summary:weekly_update >> ~/apps/my_app/current/log/summary_weekly_update.log 0 0 7 * * cd ~/apps/my_app/current && RAILS_ENV=production rake summary:weekly_update >> ~/apps/my_app/current/log/summary_weekly_update.log 0 0 14 * * cd ~/apps/my_app/current && RAILS_ENV=production rake summary:weekly_update >> ~/apps/my_app/current/log/summary_weekly_update.log 0 0 21 * * cd ~/apps/my_app/current && RAILS_ENV=production rake summary:weekly_update >> ~/apps/my_app/current/log/summary_weekly_update.log ... echo 'crontab sucks...'
This is not DRY, so we fix it…
Cron calls “rake night” every night and night takes care of the rest…
#redirect and append puts to the logfile
def logging_to(path)
FileUtils.touch([path])
$stdout = File.new(path,'a+')
yield
$stdout = STDOUT
end
#use DRY to simulate a dry run
#uses hoptoad for error recording(better than exception notifier...), get it @ hoptoad.com
def invoke_and_log_task(name)
begin
logging_to "log/#{name.gsub(':','_')}.log" do
if ENV['DRY']
puts "dry-running #{name}"
else
Rake::Task[name].invoke
end
end
rescue Exception => e
HoptoadNotifier.notify(
:error_class => "Nightly #{name} Error #{e.class}",
:error_message => "#{e.message}"
)
end
end
desc "Runs maintains tasks at night"
task :night do
invoke_and_log_task 'feed:update'
invoke_and_log_task 'summary:weekly_update' if [1,7,14,21].include? Time.now.day
ENV['greeting'] = 'Hello again...'
invoke_and_log_task 'spam_users' if Time.now.day == 5
end
Alternatively, you could just do
0 0 1,7,14,21 * * cd …
Just saying…
yeah thats right for this example.
In general it is much more convenient to have one dead-simple cronjob running (e.g. once every night) that goes through ruby where all the logic sits and can be tested, and then is executed (with loging and failure notification) then having oh-so-clever cronjobs that are hard to maintain/understand/update.
The alternative here would be to use the Whenever gem as well and have a schedule.rb built.
It also fits nicely in with capistrano. I’ve added it to my 2.3 temp;ate since I end up using cron tasks all the time.
I think this week’s RailsCast has a howto on it.
yep, this can be done with whenever/schedule, but imo the beauty of the approach is that its dead-simple, everything stays in ruby and error notifications/logs are created
Great tip!!! Thank you! I used the code today, it works beautifully.
PS – if you ever need a nice crontab web GUI, you can check out http://www.corntab.com
Cheers!
nice, ill use it if i do my next weird crontab command 🙂
Note that using the @weekly dealie in crontab is also an option.
As an application developer, I might consider doing this. As a sysadmin, I start tearing my hair out when dealing with other people’s partial crontab reimplementations. 😉