A command of the gem whenever in cron doesn't work - ruby-on-rails

I have a simple rails app with the gem whenever. And there's a module:
module Module1
class << self
def say_hi
puts "hi123"
end
end
end
When I setup whenever, it adds this to cron:
* * * * * /bin/bash -l -c 'cd /home/user123/my_app && bundle exec script/runner -e production '\''Module1.say_hi'\'''
It doesn't work. This command when I'm running it directly in the terminal returns:
/bin/bash: bundle: command not found
Then I try this:
cd /home/user123/my_app && bundle exec script/runner -e production 'Module1.say_hi'
And now an error is:
bundler: command not found: script/runner
However, my rails application is working well; bundle and other stuff are installed.

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']
chek this
If above solution don't work for you, try:
env :GEM_PATH, ENV['GEM_PATH']

Related

bundler: not executable: bin/rails in rails production while using whenever gem

I'm using whenever gem for cronjobs in rails application - production.
I'm getting an error bundler: not executable: bin/rails
scheduler.rb
every 15.minute do
runner 'TestJob.perform_later()'
end
crontab
0,15,30,45 * * * * /bin/bash -l -c 'cd /home/deploy/my-app/releases/20190719103116 && bundle exec bin/rails runner -e production '\''TestJob.perform_later()'\'''
but when i run /bin/bash -l -c 'cd /home/deploy/my-app/releases/20190719103116 && bundle exec bin/rails runner -e production '\''TestJob.perform_later()'\''' in my bash replacing bin/rails with just rails this work fine.How to fix this?
Try running it via a rake task:
config/schedule.rb
every 15.minutes do
rake 'testing:run_tests'
end
lib/tasks/testing.rake
namespace :testing do
desc 'Run tests'
task run_tests: :environment do
TestJob.perform_later
end
end
Quick Answer
With the intent of still using the original runner job type, simply add this to your schedule.rb:
set :runner_command, "rails runner"
Long Answer
The documentation isn't so clear about it, but you can see the default runner job type being set as such in Whenever's /lib/whenever/setup.rb:
job_type :runner, "cd :path && :bundle_command :runner_command -e :environment ':task' :output"
In that same file you can see that this :runner_command setting is set with:
set :runner_command, case
when Whenever.bin_rails?
"bin/rails runner"
when Whenever.script_rails?
"script/rails runner"
else
"script/runner"
end
So by default your cron command will be created using bin/rails runner unless you overide it with the above answer.

Whenever cronjobs does not run on staging

I am trying to make a simple cron job running this task:
Here is my schedule.rb:
set :environment, "staging"
set :path, "/var/www/my_app/current"
every 2.minutes do
# specify the task name as a string
rake 'cron_test'
end
Here is the task:
task :cron_test => :environment do
out_file=File.new("cron_test.txt", "w")
out_file.puts(Time.now.to_s)
out_file.close
end
I tried to do what is advised on this page but nothing works:
Cron job not working in Whenever gem
When I run crontab -l :
# Begin Whenever generated tasks for: /var/www/my_app/current/config/schedule.rb
0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58 * * * * /bin/bash -l -c 'cd /var/www/my_app/current && RAILS_ENV=staging bundle exec rake cron_test'
# End Whenever generated tasks for: /var/www/my_app/current/config/schedule.rb
When I run grep CRON /var/log/syslog:
Jun 29 17:22:01 my_server CRON[21164]: (root) CMD (/bin/bash -l -c 'cd /var/www/my_app/current && RAILS_ENV=staging bundle exec rake cron_test')
Any ideas?
Thanks
What happens when you manually run the command from crontab on the console? Try to run in. See if there are any errors.
/bin/bash -l -c 'cd /var/www/my_app/current && RAILS_ENV=staging bundle exec rake cron_test'
Might be something with local or cron environment. Also logs would be great, capturing any running errors. You can set output log to capture any problems with crontab running the command.
set :output, '/path/to/file.log'
for you example:
set :output, '/var/log/my_app.cron.log'
set :environment, "staging"
set :path, "/var/www/my_app/current"
every 2.minutes do
# specify the task name as a string
rake 'cron_test'
end
Here's the documentation whenever output redirection
Thanks it is working now!
When I created the /var/log/staging_cron.log I read this:
/bin/bash: bundle: command not found
I added env :PATH, ENV['PATH'] on the first line of my schedule.rb, updated the crontab (whenever --update-crontab) and now my test file is well created and updated.

Rails cron Whenever gem error, bundle: command not found

I've read this post Whenever errors and tried to implement the recommendations to no avail. I'm still receiving '/bin/bash: bundle: command not found' error.
On Amazon EC2.
which ruby
/usr/local/bin/ruby
which bundler
/usr/local/bin/bundler
schedule.rb
env :PATH, ENV['PATH']
require File.expand_path('../application', __FILE__)
set :output, "log/cron_log.log"
every 1.minutes do
rake "calculate:calculate"
end
crontab -e
/bin/bash -l -c 'cd /srv/www/myapp/releases/20141022032959 && RAILS_ENV=development bundle exec rake calculate:calculate --silent >> log/cron_log.log 2>&1'
tail -f log/cron_log.log
/bin/bash: bundle: command not found
When I copy the command out of crontab and run it directly, everything works fine (cd /srv/www/myapp/releases/20141022032959 && RAILS_ENV=development bundle exec rake calculate:calculate --silent >> log/cron_log.log 2>&1). It's the prepending of /bin/bash that's messing this up.
How do I get schedule.rb / whenever gem to recognize correct PATH.
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 exec"
Edit: exec added so that task can run
If none of the above solution works this did it for me without any additional setup
rvm cron setup
This will include all the right paths for gems so you do this on your machine and you are good to go.
If using rbenv, the path is "/home/YOUR_USER/.rbenv/shims/bundle", so you shoud write at the top of schedule.rb..:
set :bundle_command, "/home/YOUR_USER/.rbenv/shims/bundle exec"

How to enter rails console on production via capistrano?

I want to enter the rails console on production server from my local machine via capistrano.
I found some gists, e.g. https://gist.github.com/813291 and when I enter console via
cap production console
I get the following result
192-168-0-100:foldername username $ cap console RAILS_ENV=production
* executing `console'
* executing "cd /var/www/myapp/current && rails console production"
servers: ["www.example.de"]
[www.example.de] executing command
[www.example.de] rvm_path=$HOME/.rvm/ $HOME/.rvm/bin/rvm-shell '1.9.3' -c 'cd /var/www/myapp/current && rails console production'
/var/www/myapp/releases/20120305102218/app/controllers/users_controller.rb:3: warning: already initialized constant VERIFY_PEER
Loading production environment (Rails 3.2.1)
Switch to inspect mode.
and thats it... Now I can enter some text, but nothing happens...
Has anybody an idea how to get that work or another solution for my problem?
I've added my own tasks for this kind of thing:
namespace :rails do
desc "Remote console"
task :console, :roles => :app do
run_interactively "bundle exec rails console #{rails_env}"
end
desc "Remote dbconsole"
task :dbconsole, :roles => :app do
run_interactively "bundle exec rails dbconsole #{rails_env}"
end
end
def run_interactively(command)
server ||= find_servers_for_task(current_task).first
exec %Q(ssh #{user}##{myproductionhost} -t '#{command}')
end
I now say cap rails:console and get a console.
For Capistrano 3 you can add these lines in your config/deploy:
namespace :rails do
desc 'Open a rails console `cap [staging] rails:console [server_index default: 0]`'
task :console do
server = roles(:app)[ARGV[2].to_i]
puts "Opening a console on: #{server.hostname}...."
cmd = "ssh #{server.user}##{server.hostname} -t 'cd #{fetch(:deploy_to)}/current && RAILS_ENV=#{fetch(:rails_env)} bundle exec rails console'"
puts cmd
exec cmd
end
end
To open the first server in the servers list:
cap [staging] rails:console
To open the second server in the servers list:
cap [staging] rails:console 1
Reference: Opening a Rails console with Capistrano 3
exec is needed to replace the current process, otherwise you will not be able to interact with the rails console.
A simple Capistrano 3 solution may be:
namespace :rails do
desc "Run the console on a remote server."
task :console do
on roles(:app) do |h|
execute_interactively "RAILS_ENV=#{fetch(:rails_env)} bundle exec rails console", h.user
end
end
def execute_interactively(command, user)
info "Connecting with #{user}##{host}"
cmd = "ssh #{user}##{host} -p 22 -t 'cd #{fetch(:deploy_to)}/current && #{command}'"
exec cmd
end
end
Then you can call it say, on staging, with: cap staging rails:console. Have fun!
For Capistrano > 3.5 and rbenv. Working in 2021
namespace :rails do
desc "Open the rails console on one of the remote servers"
task :console do |current_task|
on roles(:app) do |server|
server ||= find_servers_for_task(current_task).first
exec %Q[ssh -l #{server.user||fetch(:user)} #{server.hostname} -p #{server.port || 22} -t 'export PATH="$HOME/.rbenv/bin:$PATH"; eval "$(rbenv init -)"; cd #{release_path}; bin/rails console -e production']
end
end
end
I have fiddled with that approach as well, but then resorted to avoiding building my own interactive SSH shell client and just went with this snippet I found that simply uses good old SSH. This might not be suitable if you have some weird SSH gateway proxying going on, but for logging into a box and performing some operations, it works like a charm.
In my experience, capistrano isn't built to work very well with interactive terminals.
If you have to execute things in multiple terminals, I'd suggest iterm, which has a "send to all windows" function that works very well for me:
http://www.iterm2.com/#/section/home
I have a somewhat difficult environment, which is influx ... So bash -lc isn't really an option right now. My solution is similar to #Rocco, but it's a bit more refined.
# run a command in the `current` directory of `deploy_to`
def run_interactively(command)
# select a random server to run on
server = find_servers_for_task(current_task).sample
# cobble together a shell environment
app_env = fetch("default_environment", {}).map{|k,v| "#{k}=\"#{v}\""}.join(' ')
# Import the default environment, cd to the currently deployed app, run the command
command = %Q(ssh -tt -i #{ssh_options[:keys]} #{user}##{server} "env #{app_env} bash -c 'cd #{deploy_to}/current; #{command}'")
puts command
exec command
end
namespace :rails do
desc "rails console on a sidekiq worker"
task :console, role: :sidekiq_normal do
run_interactively "bundle exec rails console #{rails_env}"
end
end
For a Rails console in Capistrano 3 see this gist: https://gist.github.com/joost/9343156
I have just used capistrano-rails-console gem to open rails console and it is working fine.

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

Resources