Tony
Tony

Reputation: 19181

Rails cron with whenever, setting the environment

This question will probably only make sense if you know about the whenever gem for creating cron jobs. I have a task in my schedule.rb like

every 1.day, :at => '4am' do
  command "cd #{RAILS_ROOT} && rake thinking_sphinx:stop RAILS_ENV=#{RAILS_ENV}"
  command "cd #{RAILS_ROOT} && rake thinking_sphinx:index RAILS_ENV=#{RAILS_ENV}"
  command "cd #{RAILS_ROOT} && rake thinking_sphinx:start RAILS_ENV=#{RAILS_ENV}"
end

However when I update my crontab using

whenever --update-crontab appname --set environment=production

the cron jobs still have RAILS_ENV=development. My tasks on production and development are the same right now, I just need to change the environment variable because thinking_sphinx needs to know the current environment. Any ideas on how to do this?

Thanks!

Upvotes: 38

Views: 47095

Answers (10)

Snips
Snips

Reputation: 6773

I was having an issue where environment wasn't being set up for whenever cron jobs - /usr/bin/bundle was being picked up instead of /usr/local/bin/bundle.

The solution was to add following to top of schedule.rb

env 'PATH', ENV['PATH']

Upvotes: 1

yogendra689
yogendra689

Reputation: 231

For Whenever (0.9.2)

Use the @environment variable for environment check:

case @environment

when 'production'

every 1.minutes do

   rake "user:take_sample"

  end

when 'development'

every 1.minutes do

  rake "user:dev_sample"

  end

end

Upvotes: 23

Jon R.
Jon R.

Reputation: 999

This questions has been open a long time so I thought I would share what worked with whenever 0.9.7, Ruby 2.4.0, and RAILS 5.0.1. In the previously mentioned answer there are a lot of close tries but syntax error plagues them. Below is what worked and is very simple approach.

schedule.rb

require File.expand_path(File.dirname(__FILE__) + '/environment')
set :output, {:standard => 'log/cron_log.log', :error => 'log/cron_error_log.log'}
env :PATH, ENV['PATH']

every :day, :at => '10am' do
     rake "somejob:run", :environment => @environment
end

Update the crontab(dev)

whenever --set 'environment=development' --update-crontab

Results(dev)

0 10 * * * /bin/bash -l -c 'cd /my/rails/app && RAILS_ENV=development bundle exec rake somejob:run --silent >> log/cron_log.log 2>> log/cron_error_log.log'

Update the crontab(prod)

whenever --set 'environment=production' --update-crontab

Results(prod)

0 10 * * * /bin/bash -l -c 'cd /my/rails/app && RAILS_ENV=production bundle exec rake somejob:run --silent >> log/cron_log.log 2>> log/cron_error_log.log'

Hopefully this can help someone out. Happy Coding this!

Upvotes: 16

Satishakumar Awati
Satishakumar Awati

Reputation: 3790

Add the following line of code at top of config/schedule.rb.

 ENV['RAILS_ENV'] = "#{@pre_set_variables[:environment]}"

and update the crontab using following command.

whenever --update-crontab pvcnxt --set 'environment=production'

and then finally restart crontab using command

service crond restart

Thats it!

Final config/schedule.rb looks this way

 ENV['RAILS_ENV'] = "#{@pre_set_variables[:environment]}"

 env :PATH, ENV['PATH']

 require File.expand_path(File.dirname(__FILE__) + "/environment")

 set :output, "#{Rails.root}/logs/cron_log_#{ENV['RAILS_ENV']}.log"

 every 1.day, :at => '00:00 am' do
  command "cd #{Rails.root}/lib/tasks && rake clean__posts_table_rake"
 end

Upvotes: 0

Trung LE
Trung LE

Reputation: 991

Whenever doesn't detect your environment, it just defaults to using production. You can set the environment for all jobs using set:

set :environment, 'staging' 

Or per job:

every 2.hours do 
  runner 'My.runner', :environment => 'staging' 
end 

Upvotes: 99

Laurynas
Laurynas

Reputation: 3869

Latest whenever allows easy Capistrano integration. You can add following to deploy.rb:

set :whenever_environment, defer { stage }
set :whenever_identifier, defer { "#{application}-#{stage}" }

require "whenever/capistrano"

Upvotes: 6

Tim Lowrimore
Tim Lowrimore

Reputation: 2052

Something else you may want to try if you're using bundler and capistrano.

In your deploy.rb file, when you set the :whenever_command, DO NOT simply do this:

set :whenever_command, "bundle exec whenever"

Instead, do this:

set(:whenever_command) { "RAILS_ENV=#{rails_env} bundle exec whenever" }

Now, the RAILS_ENV environment variable will be available when the schedule.rb file is loaded, so in schedule.rb you can now do this:

set :environment, ENV['RAILS_ENV']

Voila! You're ready to go.

Upvotes: 16

kaczor1984
kaczor1984

Reputation: 467

Watch out if you want to pass more than one param to whenever.
You have to do it like that:

whenever --update-crontab appname --set 'environment=production&cron_log=/path/to/log'

Upvotes: 12

Javan Makhmali
Javan Makhmali

Reputation:

I would consider using the "rake" shortcut to make it even cleaner:

every 1.day, :at => '4am' do
  rake "thinking_sphinx:stop"
  rake "thinking_sphinx:index"
  rake "thinking_sphinx:start"
end

Upvotes: -10

Simone Carletti
Simone Carletti

Reputation: 176552

Don't write the RAILS_ENV variable. It should set it automatically.

every 1.day, :at => '4am' do
  command "cd #{RAILS_ROOT} && rake thinking_sphinx:stop"
  command "cd #{RAILS_ROOT} && rake thinking_sphinx:index"
  command "cd #{RAILS_ROOT} && rake thinking_sphinx:start"
end

It works in my app:

every 4.days do
  runner "AnotherModel.prune_old_records"
end

$ whenever --set environment=production
0 0 1,5,9,13,17,21,25,29 * * /Users/weppos/Sites/git/app/script/runner -e production "AnotherModel.prune_old_records"

$ whenever --set environment=development
0 0 1,5,9,13,17,21,25,29 * * /Users/weppos/Sites/git/app/script/runner -e development "AnotherModel.prune_old_records"

Upvotes: 25

Related Questions