Rails cron with whenever, setting the environment
Asked Answered
N

10

38

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!

Nadaha answered 1/7, 2009 at 16:55 Comment(2)
In my particular case (starting delayed_job) I got this working using command "RAILS_ENV=#{@environment} #{Whenever.path}/bin/delayed_job start"Tropophilous
If you run rake you may also use the rake command within the whenever context.Tropophilous
S
-10

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
Scevor answered 29/7, 2009 at 19:19 Comment(3)
This answer doesn't tell how to change the environment, it's just giving a way to make the task cleaner. Check Trung LE's answer for the real way to do itChrysoberyl
Does not answer the question at all.Futtock
Please note that the rake command does in fact add the RAILS_ENV to the command that ends up in the crontab.Tropophilous
S
98

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 
Sheikdom answered 3/9, 2010 at 14:22 Comment(3)
can I pass an array to the environment hast to set multiple environments?Clave
This is not the correct way when we are dealing with multiple environmentsCountryside
What is the correct way when we are dealing with multiple environments?Sandglass
F
25

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"
Freeze answered 1/7, 2009 at 17:47 Comment(0)
P
23

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
Purport answered 30/4, 2014 at 14:50 Comment(1)
Note, however, that the @environment variable is always 'production' by default. You have to whenever --set environment=development --write-crontab when spitting out your jobs and then this answer will work.Ritual
I
16

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.

Inheritance answered 7/2, 2011 at 23:48 Comment(1)
I got this: failed: "sh -c 'cd (REMOVED)/releases/20140127213854 && RAILS_ENV=production bundle exec whenever --update-crontab (REMOVED) --set environment=production --roles db'" on (REMOVED)Spirelet
A
16

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!

Abshire answered 2/3, 2017 at 16:16 Comment(2)
env :PATH, ENV['PATH'} ??Tartan
I tried to find a document on the set method and usage it has on the output log and environment. Where can I find the info about it?Brooch
F
12

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'
Ferguson answered 2/2, 2011 at 12:18 Comment(0)
C
6

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"
Chaeta answered 29/5, 2011 at 18:50 Comment(0)
O
1

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']
Oft answered 31/5, 2019 at 13:45 Comment(0)
S
0

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
Sternutatory answered 2/12, 2015 at 12:45 Comment(0)
S
-10

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
Scevor answered 29/7, 2009 at 19:19 Comment(3)
This answer doesn't tell how to change the environment, it's just giving a way to make the task cleaner. Check Trung LE's answer for the real way to do itChrysoberyl
Does not answer the question at all.Futtock
Please note that the rake command does in fact add the RAILS_ENV to the command that ends up in the crontab.Tropophilous

© 2022 - 2024 — McMap. All rights reserved.