How to enter rails console on production via capistrano? - ruby-on-rails

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.

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.

Upstart script using foreman export is using wrong ruby version

I have just recently deployed my application to production server, but it looks that that every process I have added to my .procfile (foreman) is not started at all. Details:
I am using Rails 4.0.12, foreman 0.78.0, sidekiq 3.4.2 and clockwork 1.2.0. I am using Capistrano and I have defined a task to export procfile as an upstart service on Ubuntu 14.02. But when I start the service, no background jobs are processed. When I take look at the log files of that upstart service, I just see the following:
Your ruby version is 1.9.3, but your Gemfile specified 2.1.2
Application is running, I can see on sidekiq dashboard that nothing is processed. Based on the error message, it looks like that I am executing my procfile somehow wrong. I have tried multiple execution scenarios, but nothing seems to work. My .procfile currently looks like this:
worker: rbenv sudo bundle exec sidekiq -C config/sidekiq.yml -e production
clock: rbenv sudo bundle exec clockwork config/clock.rb
One part of exported upstart script looks like this for example:
start on starting aaa-clock
stop on stopping aaa-clock
respawn
env PORT=5100
setuid da_admin
chdir /var/www/aaa/releases/20150728172635
exec rbenv sudo bundle exec clockwork config/clock.rb
If i try the last two commands alone in bash, it works, but when i start the service "sudo service aaa start" or "rbenv sudo service aaa start", it doesn't work.
Part of deploy.rb where I am exporting my upstart service:
namespace :foreman do
desc "Export the Procfile to Ubuntu's upstart scripts"
task :export do
on roles(:app) do
within release_path do
execute :rbenv, "sudo bundle exec foreman export upstart /etc/init -a #{fetch(:application)} -u #{fetch(:user)} -l #{current_path}/log -f #{release_path}/Procfile"
end
end
end
desc "Start the application services"
task :start do
on roles(:app) do
execute :rbenv, "sudo service #{fetch(:application)} start"
end
end
desc "Stop the application services"
task :stop do
on roles(:app) do
execute :rbenv, "sudo service #{fetch(:application)} stop"
end
end
desc "Restart the application services"
task :restart do
on roles(:app) do
execute :rbenv, "sudo service #{fetch(:application)} restart"
end
end
end
Does anybody has any idea what could be wrong? I suspect, that this will be some mistake in environment configuration. Thank you in advance for your time.
EDIT:
The problem was at the end in environment of the upstart script, similar problems which pointed me in the right direction were:
foreman issue
foreman another issue
I had to create .env file with configuration of various environment variables. Now it atleast starts (other bugs arised, but they are not related to this issue).
Example of the .env file in the root of project directory:
PATH=/home/user/.rbenv/versions/2.1.2/bin:/usr/bin
RAILS_ENV=production
HOME=/home/user

Capistrano not opening rails console

I am trying to open rails console using Capistrano but its close the connection
Following script i am using and open rails console
Code
namespace :rails do
desc "Start a rails console, for now just with the primary server"
task :c do
on roles(:app), primary: true do |role|
rails_env = fetch(:rails_env)
execute_remote_command_with_input "#{bundle_cmd_with_rbenv} rails console #{rails_env}"
end
end
def execute_remote_command_with_input(command)
port = fetch(:port) || 22
puts "opening a console on: #{host}...."
cmd = "ssh -l #{fetch(:deploy_user)} #{host} -p #{port} -t 'cd #{deploy_to}/current && #{command}'"
exec cmd
end
def bundle_cmd_with_rbenv
puts "RBENV_VERSION=#{fetch(:rbenv_ruby)} RBENV_ROOT=#{fetch(:rbenv_path)} #{File.join(fetch(:rbenv_path), '/bin/rbenv')} exec bundle exec"
if fetch(:rbenv_ruby)
"RBENV_VERSION=#{fetch(:rbenv_ruby)} RBENV_ROOT=#{fetch(:rbenv_path)} #{File.join(fetch(:rbenv_path), '/bin/rbenv')} exec bundle exec"
else
"ruby "
end
end
end
Details
I am using this script to open rails console so many time ant its work but for the couple of month rails console opening script is fail and don't know what to do with this.
Output
RBENV_VERSION=2.1.2 RBENV_ROOT=/home/deployer/.rbenv /home/deployer/.rbenv/bin/rbenv exec bundle exec
opening a console on:
Usage:
rails new APP_PATH [options]
Connection to 45.55.142.39 closed.
Any Suggestion hot it will work
Something is wrong with your binstubs.
There are two things you have to do.
1) in your deploy.rb:linked_dirs should not contain the bin directory
2) This should be in your deploy.rb:
set :bundle_binstubs, nil
and after that you may run on your local machine:
rake rails:update:bin
This will include the binstubs in your repo.
Let me know how it goes.

Issue with running bundle using Capistrano

I've seen this issue in a few other questions/Github issues, but they haven't been able to shed enough light to lead to the solution.
The error:
bash: bundle: command not found
SSHKit::Runner::ExecuteError: Exception while executing as my-user#my-IP-address: cd /path-to-my-app/current ; bundle exec unicorn -D -c config/unicorn.rb -E production exit status: 127
cd /path-to-my-app/current ; bundle exec unicorn -D -c config/unicorn.rb -E production stdout: Nothing written
cd /path-to-my-app/current ; bundle exec unicorn -D -c config/unicorn.rb -E production stderr: bash: bundle: command not found
I'm using the latest version of Capistrano on my rails app. Specifically, it's a Rails 4.2.0 app with the gems capistrano-rails and capistrano-rvm.
I have a pretty standard config/unicorn.rb file, which is how I start unicorn while logged into my server. I first kill the current PID with:
kill -9 PID
Then I start unicorn with:
bundle exec unicorn -D -c /path-to-my/config/unicorn.rb -E production
This works great, but obviously I need capistrano to do that, so I essentially have those tasks in my deploy.rb file, however I get that error mentioned above. Here are the two tasks I have in deploy.rb:
namespace :deploy do
namespace :unicorn do
task :restart do
on roles(:app), in: :sequence, wait: 5 do
execute "kill -s USR2 `cat /path-to-my/tmp/pids/app-name.pid`"
end
end
desc 'Start unicorn'
task :start do
on roles(:app), in: :sequence, wait: 5 do
execute "cd #{current_path} ; bundle exec unicorn -D -c config/unicorn.rb -E production"
end
end
end
end
I have a similar task to restart DelayedJob, which throws the same error. The command is execute "cd #{current_path} ; RAILS_ENV=production bin/delayed_job -n2 restart". Like I mentioned above, when logged into the server with my user (same user I use for Capistrano), all of these tasks work as expected.
Every other built-in task works great with Capistrano, like precompiling assets, migrating my database, etc. It is the custom tasks I've added that are getting the error.
Let me know if I can add anything to help solve the problem.
Look at output of Capistrano carefully. Such commands as bundle assets:precompile makes initialization of required ruby version:
cd /<app path>/20150301211440 && ( RAILS_ENV=staging /usr/local/rvm/bin/rvm 2.1.5 do bundle exec rake assets:precompile )
Seems like you don't do it. So, probably you a using system ruby by default and it doesn't have a bundler gem.
Try to specify ruby version use RVM in your commands too. I think it should fix your problem.

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

Resources