Ruby on Rails: How can I specify runner script environment - ruby-on-rails

I am using a shell script to run some runner scripts in my Ruby on Rails app. I need to run it on the production database, but the following:
#!/bin/bash
/usr/bin/ruby RAILS_ENV=production ../script/runner ../lib/tasks.rb
gives an error:
/usr/bin/ruby: No such file or directory -- RAILS_ENV=production (LoadError)
I have tried to force it in config/environment.rb
ENV['RAILS_ENV'] ||= 'production'
or even
ENV['RAILS_ENV'] = 'production'
but even with that it still runs in development environment.
Update: I can force the scripts to connect to the right database by editing the config/database.yml file, but I wonder what's the proper way of doing it.

The help on the command line for script/runner gives you your answer.
script/runner -e production Model.method

If that's your command, the order of your arguments is your biggest problem.
/usr/bin/ruby RAILS_ENV=production ../script/runner ../lib/tasks.rb
Is different than.
/usr/bin/ruby ../script/runner ../lib/tasks.rb RAILS_ENV=production
The second example is looking for the file, the first one is setting a runtime variable while ruby interpreting it as the file you want to run.

If you redo your script like this:
#!/bin/bash
RAILS_ENV=production
/usr/bin/ruby ../script/runner ../lib/tasks.rb
...that will make it stick for the lifetime of the script. To make it stick for the lifetime of the shell's session, change it to
#!/bin/bash
export RAILS_ENV=production
/usr/bin/ruby ../script/runner ../lib/tasks.rb

You can set the environment variable like this :
RAILS_ENV=production /usr/bin/ruby ../script/runner ../lib/tasks.rb

RAILS_ENV=production script/rails runner 'user = User.find(:first, :conditions => {:admin => true}) ; user.password, user.password_confirmation = "mypasswd"; user.save!'
it worked for me

Related

When executing "bundle exec rails runner", how can I specify the application's directory?

When I execute this command:
/usr/local/bin/bundle exec rails runner -e production "load 'job_alerta_validacao.rb'"
It returns:
Could not locate Gemfile
How can I set where the application is directly in the command without needing to create a script with the "cd" command?
The most common way to use bundler is to cd to the directory containing the Gemfile. This is also the most robust way, since some other gems will probably assume that the working directory is the root of the Rails project.
If you just don't want to change your current shell's working directory, cd in a subshell:
(cd /some/directory; /usr/local/bin/bundle exec rails runner -e production "load 'job_alerta_validacao.rb'")
If you really want to execute something through bundler with a working directory other than the directory with the Gemfile, tell bundler where to find the Gemfile with the BUNDLE_GEMFILE environment variable:
BUNDLE_GEMFILE=/some/directory/Gemfile /usr/local/bin/bundle exec rails runner -e production "load 'job_alerta_validacao.rb'"

Cron + whenever not working with RVM

I am using RVM environment. RUby version : 2.1.2 rails : 4.1.1
schedule.rb :
every 1.minute do
runner "note.send_mail"
end
I used whenever --update-crontab to update the cron tab.
when I check the jobs using crontab -l it shows up as below with no proper time set up.
and the cron job does not work.
* * * * * /bin/bash -l -c 'cd /Desktop/folder1/blog2 && bin/rails runner -e production '\''note.send_mail'\'''
Can some one help me out fix this. Thanks!
Go to your ~/.rvmrc file and add the following:
rvm_trust_rvmrcs_flag=1
Then whenever --update-crontab again. According to the README of whenever:
If your production environment uses RVM (Ruby Version Manager) you will run into a gotcha that causes your cron jobs to hang. This is not directly related to Whenever, and can be tricky to debug. Your .rvmrc files must be trusted or else the cron jobs will hang waiting for the file to be trusted. A solution is to disable the prompt by adding this line to your user rvm file in ~/.rvmrc
rvm_trust_rvmrcs_flag=1
This tells rvm to trust all rvmrc files.
If that doesn't work for you, try other solutions mentioned in this page: RVM-Notes.
You could define a custom runner that loads rvm on the command line, like
job_type :runner_with_rvm, 'source /etc/profile.d/rvm.sh; cd :path;rvm 2.0#gemset do bundle exec script/rails runner -e :environment ':task' :output'
every 1.minute do
runner_with_rvm "Note.send_email"
end
Replace 2.0#gemset with your desired ruby version and gemset.
Could be that /etc/profile.d/rvm.sh is something else in your environment too.

Execute rake command inside bash

I am seeing many times the question about execution of bash files inside rake (task) files.
My question is, how to execute a rake command inside the bash file?
I have a migrate.sh file inside each rails app on my server and I'm using a general publish.sh. All of this runs ok.
Then, I have a command like rake tmp:clear assets:clean log:clear RAILS_ENV=production inside each migrate.sh that gives me a rake: command not found error.
Help?
Basically rake is not resolved as the PATH variable is not correct. You can try doing echo $PATH. Also you can create a bash script and provide some environment variables required by rake like this:
#!/bin/bash
GEM_HOME=/home/tuxdna/.gems
SHELL=/bin/bash
USER=tuxdna
PATH=/home/tuxdna/.gems/bin:/usr/lib/ruby/gems/1.8/bin/:/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games
GEM_PATH=/home/tuxdna/.gems:/usr/lib/ruby/gems/1.8
cd ~/somesite
export RAILS_ENV=production
bundle exec rake mytask:task1
klashxx's supposition was correct. It was a permissions/profile issue. I had change my user to root to be able to do other previous tasks and found out that my root was not able to run rake tasks.
This will not be an issue on production server though.
Thanks klashxx

Rails cron whenever, bundle: command not found

I am trying to use whenever to execute a rake task onces a day. Im getting this error
/bin/bash: bundle: command not found
/home/app/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/site_ruby/1.9.1/rubygems/dependency.rb:247:in `to_specs': Could not find bundler (>= 0) amongst [minitest-1.6.0, rake-0.8.7, rdoc-2.5.8] (Gem::LoadError)
from /home/app/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/site_ruby/1.9.1/rubygems/dependency.rb:256:in `to_spec'
from /home/app/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/site_ruby/1.9.1/rubygems.rb:1210:in `gem'
from /home/app/.rvm/gems/ruby-1.9.2-p180/bin/bundle:18:in `<main>'
Here is my crontab
# Begin Whenever generated tasks for: /home/af/www/app/releases/20120216172204/config/schedule.rb
PATH=/home/af/.rvm/gems/ruby-1.9.2-p180#global/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
0 0 * * * /bin/bash -l -c 'cd /home/af/www/app/releases/20120216172204 && rvm 1.9.1-p180; RAILS_ENV=production /home/af/.rvm/gems/ruby-1.9.2-p180/bin/bundle exec rake daily:stats --silent >> /home/af/www/app/releases/20120216172204/log/cron.log 2>&1'
# End Whenever generated tasks for: /home/af/www/app/releases/20120216172204/config/schedule.rb
I'm at a loss as to why it isn't working. If I run the command:
cd /home/af/www/app/releases/20120216172204 && rvm 1.9.1-p180; RAILS_ENV=production /home/af/.rvm/gems/ruby-1.9.2-p180/bin/bundle exec rake daily:stats --silent >> /home/af/www/app/releases/20120216172204/log/cron.log 2>&1
It works fine, not sure whats going on here.
You can also ensure your PATH ends up in the crontab, by putting the following at the top of the schedule.rb file:
env :PATH, ENV['PATH']
https://groups.google.com/forum/#!msg/whenever-gem/yRLt3f2jrfU/Exu3xfCo8DAJ
If above solution don't work for you, try:
env :GEM_PATH, ENV['GEM_PATH']
In my case I just ran :
rvm env --path -- ruby-version[#gemset-name]
Referring to cron job setup doc
Added new source line to the command for ruby path
before bundle command in the crontab -e
source /usr/local/rvm/environments/ruby-1.9.3-p392;
Now the commands like as below:
Before:
0 4 * * * cd /home/current && bundle exec rake my_rake RAILS_ENV=production
After:
0 4 * * * cd /home/current && source /usr/local/rvm/environments/ruby-1.9.3-p392; bundle exec rake my_rake RAILS_ENV=production
Cheers!!!
After so many try outs the following seems to work
Type the following from terminal
Type crontab -e
This opens the crontab for editing. You will see two lines as below:
# cron clears out environment variables, but Rubber.root/script/rubber uses
# "rvm do default" to run, so no longer any need to setup ruby env vars here,
# all we need is PATH
PATH=/<path to bundle>/bundle/ruby/1.9.1/bin:/usr/local/rvm/gems
AND
# Begin Whenever generated tasks for: /mnt/wamjoke-production/releases/20120912$
PATH=/<path to bundle>/shared/bundle/ruby/1.9.1/bin:/usr/local/rvm/gems
Comment out both lines beginning with PATH.
Do the above step whenever you run "bundle exec whenever" command. And it works.
No idea why PATH is misleading the environment.
I hate this problem - I've spent hours trying to solve it too.
What works for me is to add
RAILS_ENV=production; source /usr/local/rvm/scripts/rvm;
before the bundle command.
Forget about PATH settings in cron files. Setting the PATH does not work.
Set the path to bundle explicitly in your config/schedule.rb
set :bundle_command, "/usr/local/bin/bundle"
You can try below solution which I found while googling and that works for me finally....hope that should work with you.
I implemented and tested the same on production make sure that to change environment accordingly -
set :output, "{your path on the server}/log/cron_log.log"
set :environment, :production
env :PATH, ENV['PATH']
job_type :rbenv_rake, %q!eval "$(rbenv init -)"; cd :path && :environment_variable=:environment bundle exec rake :task --silent :output!
Best luck, This issue occurred after 3 years as I was using before just simple what given on the gem documentation on production.
I'm using Ruby 2.x and Rails 4.2 with whenever 0.9.4 latest version. It should work with earlier version as well, if the nature of the issue is same.
thank you.
I think you should try explicitly setting the GEM_HOME and GEM_PATH environment variables in your crontab. You could also try running something like gem list --local or gem environment through cron and checking the output.
I played around with this all afternoon and couldn't find a better solution. Here is what I have come up with
bundle install --binstubs
and then run
bin/rake daily:stats
By executing a command that way: /bin/bash -l -c
You are launching a bash command as a login shell which is going to source (execute) /etc/profile bash file as a setup file. By doing so, if you check this file, it might have bash command lines that erase your previous $PATH which you do not want to since it contains your path to your bundle and all your other commands in the first place.
To fix this issue you just have to remove the lines related to set up the $PATH variable in your /etc/profile file.
This is a ENV['PATH'] not set issue. The most elegant way to fix this is to append the rvm related scripts to the path right after the install. Add the following lines to beginning of .bashrc ( beginning and not end as when .bashrc is accessed by a non-interactive shell, the line [ -z "$PS1" ] && return throws error and the subsequent lines are not executed.
PATH=$PATH:$HOME/.rvm/bin # Add RVM to PATH for scripting
[[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm"
and not try to explicitly set PATH and sully environment variables.
For those using rbenv you can use the included shim /home/username/.rbenv/shims/bundle
0 0 * * * /bin/bash -l -c 'cd /home/af/www/app/releases/20120216172204 && RAILS_ENV=production /home/af/.rbenv/shims/bundle exec rake daily:stats --silent >> /home/af/www/app/releases/20120216172204/log/cron.log 2>&1'
in 2021, I found a basic solution, just add on top of schedule.rb
env :PATH, ENV['PATH']
set :output, "log/cron_log.log"
set :runner_command, "rails runner"
from:
https://github.com/javan/whenever/issues/665
I solved this problem by printing out my environmental variables
printenv
finding the ones that look related to Rails. One was a path to gems, the other was GEM_HOME and prepending the command in cron with these two:
PATH=$PATH:/home/petr/gems/bin GEM_HOME=/home/petr/gems program_executable
Also in 2021, adding this in schedule.rb worked for me:
set :job_template, "bash -l -c 'PATH=#{ENV['PATH']} && :job'"
All jobs are by default run with bash -l -c 'command...' (https://github.com/javan/whenever)
So I made bash include ENV['PATH'] in PATH at the beginning and now rails are called from the proper rbenv.
For modern fix, add this line in capistrano deploy.rb,
set :whenever_command, "bundle exec whenever"
[root#smbserver current]# crontab -e
02 22 * * 1-5 /bin/bash -l -c /shell/day.sh
30 14 * * 0 /bin/bash -l -c /shell/week.sh

How to set rails_env for a script or batch file

I put my batch file in lib folder
and use rails db configuration, active-record like this.
require "#{File.dirname(__FILE__)}/../config/environment.rb"
class Batch
def hello
Message.new do |t|
t.title = "hello"
t.save
end
end
end
batch = Batch.new
batch.hello
when excute batch
ruby lib/batch.rb
in development environment it's ok
but production environment still save development database...
how do i set rails_env batch.rb like this
ruby lib/batch.rb RAILS_ENV=production
To initialise the Rails environment, instead of putting
require "#{File.dirname(__FILE__)}/../config/environment.rb"
launch your batch file using script/runner and specify the environment with the -e option
e.g.
script/runner -e production lib/batch.rb
I think the above is The Rails Way of writing and executing a script that needs the Rails framework initialised in order to work. The alternative, as neutrino says, is to prefix the command with RAILS_ENV=value e.g.
$ RAILS_ENV=production lib/batch.rb
This is a standard shell feature to set an environment variable prior to executing a command.
Just FYI without script/runner :
RAILS_ENV=production ruby lib/batch.rb

Resources