I frequently need to run the command "Rails.cache.clear" on Heroku and the only way I have found to do it is to first run "heroku run console" and then run the command. Any way to do it in one step?
This seems to work:
echo "Rails.cache.clear; exit" | heroku run console
Without the exit it seems to hang for some reason, at least for me.
I think this is what you're looking for:
heroku run rails runner -e production Rails.cache.clear
If you don't set the environment, development will be used.
If it's a common task like clearing the cache, make a rake task.
Create a rake task with the command. For example a file lib/tasks/cache.rake
namespace :cache do
desc 'Clear memcache'
task :clear => :environment do
Rails.cache.clear
end
end
Then you can run the command
heroku run rake cache:clear
Related
I'm trying to execute a simple rake task using whenever gem but the code isn't being executed.
I already set the environment to development, I updated the cron using the whenever --update-crontab command and the rake task works well if I run the command on console. But, when I run the server the log file is not being generated.
I saw a question here too with the same problem but it was solved setting the environment to development, but didn't work out for me.
My rake task:
namespace :testando do
task :consulta => :environment do
produto = Produto.first
puts produto.nm_produto
end
end
My schedule.rb:
set :output, "#{path}/log/cron_log.log"
set :environment, 'development'
every 1.minute do
rake "testando:consulta"
end
I'm using rails 5.0.0.1 and I'm programing in Cloud9, so I think the OS is Ubuntu.
What's missing ?
Update:
I followed the instructions of the main answer in this topic Cron job not working in Whenever gem
And it worked! The task is running even with the server not being started (with "rails s" command).
please run crontab -l to see if you have updated the crontab successfully
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.
I'm running a small demo site. I'd like to reset the database once an hour or so (automatically, not manually). I could write a rake task to destroy records for each of the models. Is there a simpler approach?
How best to accomplish this?
You can use Heroku Scheduler to schedule a rake task. If you rake task runs with heroku run then it works with scheduler too.
Please refer this link to how to automate rake task on heroku
http://kakimotonline.com/2014/04/27/using-rake-to-automate-heroku-tasks/
Your rake file will look something like this:
namespace :heroku do
def run_command(cmd, app_name)
Bundler.with_clean_env do
sh build_command(cmd, app_name)
end
end
def build_command(cmd, app_name)
"heroku #{cmd} --app #{app_name}"
end
end
Following the example linked by Akshay, I was able to get this working, although not exactly as I planned.
First, a clarification. To add the scheduler add-on on Heroku, you have to provide your credit card number. I'm still getting my bearings with the Heroku platform and am not ready to do that quite yet. So my solution works without the scheduler add-on. Instead it runs as a rake task from your local dev environment and uses the heroku toolbelt to run the reset command on your remote app.
If you are looking to run everything on Heroku, I don't think this will work as you can't run the heroku pg:reset command on Heroku itself. However, it looks like this solution here would work.
Now to my solution.
First, create the following rake file:
# lib/tasks/heroku.rake
namespace :heroku do
# bundle exec rake heroku:reset_db['my-app-name']
# Note: run locally with Heroku toolbelt to reset DB on app
desc 'Reset database with seed data'
task :reset_db, [:app_name] do |t, args|
run_command("pg:reset DATABASE_URL --confirm #{args.app_name}", args.app_name)
run_command("run rake db:migrate", args.app_name)
run_command("run rake db:seed", args.app_name)
end
# Helper Functions
# Source: http://kakimotonline.com/2014/04/27/using-rake-to-automate-heroku-tasks/
def run_command(cmd, app_name)
Bundler.with_clean_env do
sh build_command(cmd, app_name)
end
end
def run_command_with_output(cmd, app_name)
Bundler.with_clean_env do
`#{build_command(cmd, app_name)}`
end.gsub("\n", "")
end
def build_command(cmd, app_name)
"heroku #{cmd} --app #{app_name}"
end
end
Now you can reset your database by running the following rake command from your local environment with your app name (run heroku apps for your app name):
bundle exec rake heroku:reset_db['my-app-name']
And if you want to schedule it to run at regular intervals as I did, add a job to your local crontab (which is a little more complicated than just copying the line above):
# Reset Heroku database hourly
RBENV_SHIM=/home/klenwell/.rbenv/shims/
RBENV_BIN=/home/klenwell/.rbenv/bin
RAILS_APP=/home/klenwell/projects/my-app-name
HEROKU_LOG=/tmp/heroku-cron.log
0 * * * * export PATH=$RBENV_SHIM:$RBENV_BIN:$PATH; eval "$(rbenv init -)"; cd $RAILS_APP && bundle exec rake heroku:reset_db['my-app-name'] >> $HEROKU_LOG 2>&1
For more info on setting up a cron job to run a rake task with rbenv, see this article.
rake db:schema:load accomplishes what you want, though I've never tried running it on Heroku.
You could also try the database_cleaner gem, which is typically used in test environments.
Try heroku run rake db:setup.
But you will have to run it manually anytime you need to.
Im scratching my head here wondering if I'm barking up the wrong tree. I have a server which I've deployed a Rails app onto using Capistrano. Recently I added a new data type to one of the models, and now I need to run a Rake task to update the existing records.
After a lot of Googling I'm starting to wonder if people use Rake tasks with Capistrano. Some forum posts from 2013 or so mention that Capistrano supports the .rake extension. Whereas other posts I've found indicate that Capistrano has its own task automation system, and is incompatible with rake.
I found Cape, but I'm unsure if this is what I'm looking for as it seems to convert Rake tasks into cap recipes. Its possible I'm mistaken on this point, I really don't have any experience working with Capistrano or even working in the full stack spectrum.
What I'm wondering is this: How do I run a simple Rake task on my remote server?
Some quick points for clarity, I've installed the app on the latest Ubuntu LTS, 14.10 if memory serves. I followed the tutorial found here. I have full sudo access and I can ssh into the server.
thanks in advance for helping a noob
If you need to update models, you can of course write a Rails migration - this will ensure that it's run if it hasn't been run yet.
The easiest way to execute a rake task on the server would be just via ssh if it's a one-time task. See the last paragraph in the tutorial you mentioned:
cd /opt/www/testapp/current ; bin/rake RAILS_ENV=production db:seed
To answer your original question about rake: you can execute rake tasks via capistrano similar to how you would execute it locally, only within the capistrano script. Here's an example:
deploy.rb:
namespace :rake do
desc "My task"
task :my_task do
on roles(:app) do
within "#{current_path}" do
with rails_env: :production do
execute :rake, "my_task"
# !!!see NOTE at end of answer!!!
end
end
end
end
end
You can view all your cap tasks via cap -T locally. The capistrano task I wrote above should show up as cap tasks:my_rake_task.
If you want to be ably to run any available rake task without configuring, do the following:
namespace :rake do
desc "Invoke rake task"
task :invoke do
on roles(:app) do
within "#{current_path}" do
with rails_env: :production do
execute :rake, ENV['task']
# !!!see NOTE at end of answer!!!
end
end
end
end
end
Then you can write:
cap production deploy:invoke task=my:rake:task
NOTE: you might want to replace the execution line with
run "bin/rake RAILS_ENV=#{rails_env} #{ENV['task']}"
to use the same syntax as the tutorial (without the binstubs you might need to configure capistrano/bundler and capistrano/rbenv first ...)
Check out capistrano-rake
Once installed, run any rake task on your production/staging servers without messy capistrano recipes by simply doing this:
$ cap production invoke:rake TASK=your:rake:task
Full Disclosure: I wrote it
I'd like to learn how to build a rake task for my rails 3 app that does two things.
Pushes assets to the CDN
Deploys to heroku
Commands for the above steps:
rake cache:s3
heroku jammit:deploy --app #{app}
Here's what I have /lib/tasks/deployer.rake
task :deployit do
puts '=== Storing assets on s3 ==='
run "rake cache:s3"
puts '=== Deploying to Heroku ==='
run "heroku jammit:deploy --app #{app}"
end
def run(cmd)
shell cmd
if $?.exitstatus == 0
display "[OK]"
else
display "[FAIL]"
end
end
But that errors with 'undefined method `shell' for main:Object'
Suggestions on how to make this work? Should this be a task or something else?
Thanks
The first task is another rake task, which will run if it is a dependency of the :deployit task. Your current code would loads rake twice.
If you use system like Arun suggested you would get:
task :deployit => 'cache:s3' do
puts '=== Deploying to Heroku ==='
system "heroku jammit:deploy --app #{app}"
end
Use system command instead. For more info: http://blog.jayfields.com/2006/06/ruby-kernel-system-exec-and-x.html