rake task via cron problem loading rubygems - ruby-on-rails

I have managed to get a cron job to run a rake task by doing the following:
cd /home/myusername/approotlocation/ && /usr/bin/rake sendnewsletter RAILS_ENV=development
i have checked with which ruby and which rake to make sure the paths are correct (from bash)
the job looks like it wants to run as i get the following email from the cron daemon when it completes
Missing these required gems:
chronic
whenever
searchlogic
adzap-ar_mailer
twitter
gdata
bitly
ruby-recaptcha
You're running:
ruby 1.8.7.22 at /usr/bin/ruby
rubygems 1.3.5 at /home/myusername/gems, /usr/lib/ruby/gems/1.8
Run `rake gems:install` to install the missing gems.
(in /home/myusername/approotlocation)
my custom rake file within lib/tasks is as follows:
task :sendnewsletter => :environment do
require 'rubygems'
require 'chronic'
require 'whenever'
require 'searchlogic'
require 'adzap-ar_mailer'
require 'twitter'
require 'gdata'
require 'bitly'
require 'ruby-recaptcha'
#recipients = Subscription.all(:conditions => {:active => true})
for user in #recipients
Email.send_later(:deliver_send_newsletter,user)
end
end
with or without the require items, it still gives me the same error ...
can anyone shed some light on this? or alternatively advise me on how to make a custom file within the script directory that will run this function (I already have a cron job working that will run and process all my delayed_jobs.
After Jonathans suggestion below I ran
env
as a cron job on its own and received the following output:
SHELL=/bin/sh
MAILTO=myemailaddress
USER=myusername
PATH=/usr/bin:/bin
PWD=/home/myusername
SHLVL=1
HOME=/home/myusername
LOGNAME= myusername
_=/usr/bin/env
does this mean it's not loading the ruby files properly?
....
also took Jonathans advice and produced the following cron.sh file
#!/bin/sh
date
echo "Executing Matenia Rake Task"
PATH=/usr/bin:/bin
cd /home/myusername/approotlocation/
rake sendnewsletter
still getting the missing gems notice ...
Cheers!

Easiest way to fix this (but kind of a shotgun approche) is from your shell type
env | grep PATH
Then take this output and add it your crontab for that user
so it would look something like this
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
# m h dom mon dow user command
42 6 * * * root job1
47 6 * * 7 root job2
52 6 1 * * root job3
Just make sure your gems's are inside of that path

When cron runs, it executes with a very minimal environment. Try running a cron job that just does env or which ruby, and you may see that your PATH is not the same as your interactive shell path. You'll need to specifically set the PATH in .bash_profile or another shell startup file.

I got around all of this by making a custom script/file and running that through cron. I dont know how, but it managed to work ...
Thanks for all the efforts.

Related

Cronjobs for Rails stopped working after switching to asdf

I recently changed from rvm to asdf.
Since then, I can't get cronjobs to run.
crontab -l
* * * * * /bin/bash -l -c 'cd /var/www/jobs/code && RAILS_ENV=production bundle exec rake cron_test' >> /tmp/cron_test_output 2>&1 /tmp/cron_error
gives me /tmp/cron_error: bundle: command not found. There is no output to stderr.
gem install bundler has not worked for the jobs user.
Not sure where to install bundler to make this work.
The rake tasks work when run independently. The cronjobs that are not rake tasks run. Cron is working.
Edit:
While the cronjobs were working before, they obviously can't now find the location of bundler. By changing bundle exec to the full path /home/jobs/.asdf/shims/bundler exec, I have managed to get this to work.
I have been using the whenever gem to create cron jobs for rake tasks. Turns out the easiest way to get around this problem is to make sure that the environment path is included in the whenever generated crontab.
within config/schedule.rb for the whenever gem, I added the following:
env :PATH, ENV['PATH']
and now everything is working as the cron job can now find the bundler.
Based on this issue from the whenever gem.
And this one too.

Cron job not being updated by whenever gem

Having a series of rake tasks that should be translated by the whenever gem into the cron file, I was wondering why the takes shows were pointing to an old release.
It cannot be asserted that whenever is active somehow, even though it is listed in the gem file (and associated lock file) and deployment refers to whenever in the deployment as follows:
tar: DEBUG [1f7d4e56] bin/whenever: time stamp 2016-01-08 15:01:20 is 88.787104175 s in the future
update Checking bundle exec whenever -v returns the proper version. Need bundle exec there...
Capfile includes require "whenever/capistrano" after calls to bundler and rails.
require 'capistrano/bundler'
require 'capistrano/rails'
require 'whenever/capistrano'
Note: this is being tested in development mode.
Functional answer. The instructions are misleading If you don't need different jobs running on different servers in your capistrano deployment, then you can safely stop reading now and everything should just work the same way it always has. Keep on reading.
The nugget is nested after this statement. Roles default to [:db]. Thus two sources of error are possible:
different job_roles on different machines are not specified in schedule.rb
Check your environment file. If "db" is not listed, whenever will not fire.
I had the same issues with using Capistrano whenever plugin, I solved it by making custom deploy shell scripts, cap production deploy being one command of many, and then inclding cap production cron:regen; inside this script I called deploy.sh, with the command inside the deploy.rb being:
namespace :cron do
desc "restart cron"
task :regen do
on roles(:app) do |host|
rails_env = fetch(:stage)
execute_interactively "crontab -r;bundle exec whenever --update-crontab;crontab -l;"
end
end
end
def execute_interactively(command)
port = fetch(:port) || 22
exec "ssh root##{fetch(:ip)} -t 'cd SERVER_PATH_OF_YOUR_APP && #{command}'"
end
I use these functions for all types of different commands, since Capistrano still gives me problems with a lot of native plugins it uses.
If you're not happy with the whenever/capistrano, you can create yourself a simple Capistrano task to update the cron jobs:
namespace :deploy do
desc "Update crontab with whenever"
task :update_cron do
on roles(:app) do
within current_path do
execute :bundle, :exec, "whenever --update-crontab #{fetch(:application)}"
end
end
end
after :finishing, 'deploy:update_cron'
end
The task will be called when the code deployment is finished.

Can't execute Rails rake task with cron

I'm trying to run rake task with cron on Ubuntu with rvm
My crontab -l
* * * * * cd /media/sf_visa-tracker/ && /home/ruslan/.rvm/gems/ruby-2.1.0/bin/rake parse RAILS_ENV=production >> /var/log/visa-parse.log 2>&1
which rake says
/home/ruslan/.rvm/gems/ruby-2.1.0/bin/rake
And I keep getting this error in my log (/var/log/visa-parse.log)
/usr/bin/env: ruby_executable_hooks: No such file or directory
Also, if I run cd /media/sf_visa-tracker/ && /home/ruslan/.rvm/gems/ruby-2.1.0/bin/rake parse RAILS_ENV=production from my terminal, rake task works.
Pls help ;)
The simplest way to use rvm with cron is to use rvm's wrappers. Your shell sets up a whole bunch of rvm-related environment when it starts, and that's missing from your cron job. The wrappers are versions of the Ruby-related commands that take care of this for you.
In this case, if you have rvm installed to /usr/local, your cron job should look something like this:
* * * * * cd /media/sf_visa-tracker/ && /usr/local/rvm/wrappers/ruby-2.1.0/bin/rake parse RAILS_ENV=production >> /var/log/visa-parse.log 2>&1
You could also bundle up your rvm setup into a shell script that loads rvm before invoking rake; there's more details of both approaches in rvm's documentation on working with cron.
I struggled to get something that worked and seemed clean. Here's what I ended up doing in case it helps.
crontab
0 5 * * * /home/deploy/apps/myproject/shared/cron/daily_updates.sh
I put the script in myproject/shared since I'm using Capistrano and that seemed like a good place for things that would persist between releases.
shared/cron/daily_updates.sh
#!/usr/bin/env bash
# You will need to update this as you bump ruby versions
source /home/deploy/.rvm/environments/ruby-2.3.1#myproject
# Since I had a separate place for Rails specific environment variables (e.g. secrets, app keys)
# you should set the permissions on that file to be owner read/write only
source /home/deploy/.rails_env
cd /home/deploy/apps/myproject/current
rake RAILS_ENV=production daily_update:send_updates 2>&1

Run ruby on rails on upstart

I'm folowing this link to put ruby on rails start automatically.
But I cant understand its ruby code
#!/usr/bin/env ruby
require File.expand_path("../../config/environment", __FILE__) #1.what is this path?
STDOUT.sync = true
Stalker::job 'user.fetch_details' do |args| #2.what is this user?
begin
user = User.find(args['id']) #3.what is this id?
user.fetch_user_details!
rescue ActiveRecord::RecordNotFound # too fast
Rails.logger.warn "Unable to find user ##{args['id']} - suspect too fast, requeuing"
Stalker.enqueue('user.fetch_details', :id => args['id'])
end
end
jobs = ARGV.shift.split(',') rescue nil
Stalker.work jobs
and conf file code in /etc/init/
description "TweetedLinks Ruby Worker"
# automatically start
start on filesystem
# working directory
chdir /var/www/TweetedLinks/current #4.should I change this to my own dir?ie home/usr/Trail/test-app
# command to run, with Bundler support!
env RAILS_ENV=production
exec bundle exec ruby script/worker.rb >> log/worker.log #5.do i need to create this worker.log? and this script folder can be put anywhere?
respawn
I have my rails app under home/usr/Trail/test-app
I have create a script folder under home/usr/script
I have my rvm generated under home/usr/.rvm/wrapper/test-app
How to modify this code according to my situation.
and the 5 question in code comments I also very confuse.
Thanks in advance!have been stuck for month!
The easiest way would be to use foreman gem that can export Procfile to upstart, see http://ddollar.github.io/foreman/#UPSTART-EXPORT

clean directory with whenever gem

I have installed whenever gem:
I want to clean the directory public/uploads/tmp in my app ruby on rails 3.1 each 5 minutes.
every 5.minutes do
#here go the code for clean the directory tmp
end
How can I do it?
Thank you!
You could try using FileUtils#rm_rf included in the standard library. For example:
FileUtils.rm_rf Dir.glob("#{Rails.root}/public/uploads/tmp/*")
Edit (to use it with whenever gem)
An approach by using a rake task could be:
1) Create a rake task in f.ex: lib/tasks/cleanup.rake with something similar to the following:
require 'fileutils'
namespace :app do
desc "Cleanup temp uploads"
task :cleanup => :environment do
FileUtils.rm_rf Dir.glob("#{Rails.root}/public/uploads/tmp/*")
end
end
2) In config/schedule.rb (created by whenever after running the wheneverize command):
every 5.minutes do
# run the previous app:cleanup task
rake "app:cleanup"
end
3) Whenever is only a wrapper to easily define crontab jobs, so now we need to export the defined schedule into the crontab file for the current user. To do that we should type from the application root:
bundle exec whenever -w
4) You can check that it worked by typing crontab -l and you should the something like the following:
# Begin Whenever generated tasks for: /tmp/whene/config/schedule.rb
0,5,10,15,20,25,30,35,40,45,50,55 * * * * /bin/bash -l -c 'cd /tmp/whene && RAILS_ENV=production bundle exec rake app:cleanup --silent
As a side note, if you want the operation to write some log output, please check this page on the whenever github wiki.
Hope it helps.

Resources