How to run a rake task regularly with using CRON? - ruby-on-rails

I've written a rake task for my Rails application and I'd need to run this tasks regularly with using CRON.
If I have a URL that I need to ping with CRON, I do it like this:
0 */6 * * * curl https://www.website.com/something
But how to "ping" a rake task?
The application is located in /home/deployer/apps/myapp-production/current and is running on DigitalOceal (Ubuntu server - nginx).
Thanks.
EDIT: This is my command:
0 */6 * * * cd /home/deployer/apps/myapp-production/current && RAILS_ENV=production bundle exec rake db:backup
But the output is:
/bin/sh: 1: bundle: not found
When I run just rake db:backup on my laptop (locally), everything works just well.
Do I have incorrect the path in the CRON task?
EDIT2: When I run the command cd /home/deployer/apps/myapp-production/current && RAILS_ENV=production bundle exec rake db:backup manually from the command line, everything is working, but not from the CRON.

Use whenever gem. It provides nice DSL like:
every :day, :at => '12:20am', :roles => [:app] do
rake "app_server:task"
end

Related

How can I run a rake task via cron?

I have and rails application and a rake task which I'm going to execute by cron around once in an hour. But the thing is that the task uses rails environment and some classes of my rails application. If I run it as ruby script, I'll have to include all the dependencies it uses and I think it's not possible to do it correctly and in a simple way. So I'll have to run it as a rake task because it'll preserve all the dependencies, right? Then how can I run a rake task from cron?
Note that I prefer not to use any third-party solution when there's no necessity, in this case I don't want to use the gem whenever or the like.
You can add to your crontab something like
0 * * * * /bin/bash -l -c 'cd /path/to/your/project && bundle exec rake foo:bar >> log/cron.log 2>&1'
This will run foo:bar task every hour and write stdout and stderr to log/cron.log.
Please notice bundle exec before rake command.
Using bundler ensure you that task will fetch correct environment.
To specify RAILS_ENV you can do
... && RAILS_ENV=production bundle exec rake foo:bar
Use whenever to simplify your life https://github.com/javan/whenever ;)
Here's an example of a rake task:
task :foo => :environment do
puts "Running rake task in environment: #{Rails.env}"
# can access Models here or whatever
end
Note that the => :environment part is optional, but it what makes your Rails environment to the task block.
You can put rake run_my_task in your cron job.
You may need to use something like cd /home/$USER/my_rails app && rake run_my_task to ensure that the cron runs the task from the Rails root directory.

Backup a Ruby in Rails app (Gitlab) with Cron job

I tried ti backup my gitlab project (it's based on ROR) with a bash script triggered with a CRON job.
The bash script is ok except the rake migrations wiche returns an error:
gitlabBackUp.sh: 12:
/home/backup/scripts/gitlabBackUp.sh: bundle: not found
Here is the way i did it in my gitlabBackUp.sh
# Export the data
bundle exec rake gitlab:backup:create --trace RAILS_ENV=production
I tried without the bundle exec but it returns
/home/backup/scripts/gitlabBackUp.sh: 14:
/home/backup/scripts/gitlabBackUp.sh: rake: not found
Any tips?
EDIT:
I finally get the cron task get working with:
/usr/local/bin/bundle exec /usr/local/bin/rake gitlab:backup:create --trace RAILS_ENV=production
PATH is probably not well specified in cron. You can:
1) Call (exec) bash with -l e.g. exec bash -l /path/to/real-script.sh
Or perhaps directly in cron like 0 16 * * * /bin/bash -l '/home/backup/scripts/gitlabBackUp.sh'
2) Explicitly specify path for bundle and rake e.g. /usr/local/bin/bundle exec /usr/binrake gitlab:backup:create --trace RAILS_ENV=production
You can always know the location of bundle and rake through which bundle and which rake; or type -P bundle and type -P rake.

Capistrano: trying to run rake db:seed on remote server

I'm trying to run my seed file on a remote server using capistrano. My deploy is OK, so there is no issue there. Here is the code for running the seed file in config/deploy.rb
namespace :seed do
desc "Run a task on a remote server."
# run like: cap staging rake:invoke task=a_certain_task
task :default do
run("cd #{deploy_to}/current; /usr/bin/env bundle exec rake #{ENV['db:seed']} RAILS_ENV=#{rails_env}")
end
end
I am evoking this task by running 'cap seed'.
Whats weird is it looks like tests are running when I run this..HERE is a snippet.
Maybe the problem is with #{ENV['db:seed']} part. Isn't it should be just db:seed. The eniviroment variable db:seed doesn't exist so You are calling a pure rake command.
Try this:
run("cd #{deploy_to}/current; /usr/bin/env bundle exec rake db:seed RAILS_ENV=#{rails_env}")

Automatically Starting ElasticSearch with Rails

I've been doing Ruby on Rails development with ElasticSearch between two machines and its starting to get a little annoying. My usual workflow is:
git pull
bundle install
rake db:migrate (or rake db:setup depending)
rails server
elasticsearch -f -D myconfig.xml
rake environment tire:import CLASS=MyObject FORCE=true
Is there anyway I can add all of these commands to some type of start up script in Rails to bring them all into one place? It would make bringing up a dev environment a lot easier on me everytime I switch machines.
The best way I've found is to use the Foreman gem to kickstart your project and associated processes.
It looks like you should do this in your deployment using Capistrano. Here is an example config/deploy.rb file:
[basic parts omitted]
after "deploy", "bundler:bundle_install"
after "bundler:bundle_install", "db:db_migrate"
after "deploy:db_migrate", "deploy:elastic_search_indexing"
namespace :bundler do
desc 'call bundle install'
task :bundle_install do
run "cd #{deploy_to}/current && bundle install"
end
end
namespace :db do
desc 'fire the db migrations'
task :db_migrate do
run "cd #{deploy_to}/current && bundle exec rake db:migrate RAILS_ENV=\"production\""
end
end
namespace :elasticsearch do
desc 'run elasticsearch indexing via tire'
task :index_classes do
run "cd #{deploy_to}/current && bundle exec rake environment tire:import CLASS=YourObject FORCE=true "
end
end
[rest omitted]
Make sure you have a config file on the target machine (Linux) in /etc/elasticsearch/elasticsearch.yml with contents like:
cluster:
name: elasticsearch_server
network:
host: 66.98.23.12
And the last point to mention is that you should create an initializer config/initializers/tire.rb:
if Rails.env == 'production'
Tire.configure do
url "http://66.98.23.12:9200"
end
end
As you can see, this is the exact same IP address, but only used for the production environment. I assume that you access elasticsearch locally (in development mode) via localhost. elasticsearch is connection per default to
http://0.0.0.0:9200
A good starting point and also in depth help is provided by awesome Ryan Bates and his Railscasts http://railscasts.com/episodes?utf8=%E2%9C%93&search=capistrano
Whats keeping you from putting it in a bash script? And put the script inside your RAILS_APP_HOME/scripts folder?
#!/bin/sh
git pull
bundle install
rake db:migrate
rails server
elasticsearch -f -D myconfig.xml
rake environment tire:import CLASS=MyObject FORCE=true

Rake Task from Crontab?

Stack:
Apache2
Rails 2.3.8
RedHat Linux
Ruby Enterprise 1.8.7
Got the following rake task in my app user's crontab which is meant to pull records into a database table every 15 min:
*/15 * * * * app_user cd /var/www/apps/my_app/current/ && rake thing:do_stuff RAILS_ENV=production
I can see that the cron daemon is running this task in the cron log, but the database table it's supposed to pull records into doesn't change. This task is working without error when I run it manually in the /var/www/apps/my_app/current directory, and pulls records into the table as I expect it to.
I reset the PATH variable in the crontab to reflect using REE, thinking maybe the default path wouldn't jive with /opt/ruby-enterprise...
How do I get this rake task to actually run with cron?
0,15,30,45 * * * * /bin/bash -l -c 'cd /var/www/apps/my_app/current && RAILS_ENV=production bundle exec rake thing:do_stuff --silent'
Try to use full path to rake binary (run in console which rake and replace rake with full path).
For example, if which rake returns the following path:
/Users/bob/.rvm/gems/ruby-1.9.3-p194/bin/rake
You should use the following command to run the rake task:
/Users/bob/.rvm/bin/rvm all do bundle exec rake allocator:snapshot
and I prefer whenever gem for cron jobs in ruby
How to detect if task failed in cron? On fail cron tries to send email. So you can configure postfix to use your smtp settings (from google for example), and add file ~/.forward containing only your email to home directory of user who is running that cronjob in your system.

Resources