Sarun Sermsuwan
Sarun Sermsuwan

Reputation: 3818

Capistrano 3: bundler not recognized when running custom shell command

I'm having an issue implementing Capistrano deployment with jruby on RVM. I'm using PUMA as app server and that requires me to add capistrano3-puma in my Gemfile. All in all, everything seems to work perfectly, my server's code got up-to-date fine from the git repo, and had the previous version of code archived nicely. Except, every time I try to run shell command from Capistrano task, such as, "bundle exec pumactl -F config/puma.rb start", for example, Capistrano can't seem to recognise bundle command.

My real case example is shown as below, when I run the above mentioned command in an overrided deploy:start method it return an error "bundle: command not found". I already tested the same command works fine, when I log on to the server via SSH and launch it from the app folder directly.

jruby 1.7.16.1 (1.9.3p392) 2014-10-28 4e93f31 on OpenJDK 64-Bit Server VM 1.7.0_65-b32 +jit [linux-amd64]
** Invoke deploy:start (first_time)
** Execute deploy:start
INFO[fc57a7d8] Running /usr/bin/env cd /var/appname/current &&  bundle exec pumactl -F config/puma.rb start on 192.168.2.6
DEBUG[fc57a7d8] Command: cd /var/appname/current &&  bundle exec pumactl -F config/puma.rb start
bind address: 
port: 22
host: 192.168.2.6
options: {:auth_methods=>["none", "publickey", "password", "keyboard-interactive"], :send_env=>[/^LANG$/, /^LC_.*$/], :user=>"root
", :forward_agent=>true, :logger=>#<Logger:0x14c7b324 @logdev=#<Logger::LogDevice:0x42c20b24 @filename=nil, @shift_age=nil, @dev=#
<IO:fd 2>, @mutex=#<Logger::LogDevice::LogDeviceMutex:0x51698ab9 @mon_count=0, @mon_mutex=#<Mutex:0x6812a170>, @mon_owner=nil>, @s
hift_size=nil>, @formatter=nil, @progname=nil, @default_formatter=#<Logger::Formatter:0x1f24f571 @datetime_format=nil>, @level=4>}
DEBUG[fc57a7d8]         ***bash: bundle: command not found***
cap aborted!
Exception while executing on host 192.168.2.6: cd /var/appname/current &&  bundle exec pumactl -F config/puma.rb start exi
t status: 127
cd /var/appname/current &&  bundle exec pumactl -F config/puma.rb start stdout: Nothing written
cd /var/appname/current &&  bundle exec pumactl -F config/puma.rb start stderr: Nothing written
/Users/dev/.rvm/gems/[email protected]/gems/sshkit-1.5.1/lib/sshkit/command.rb:97:in `exit_status='
/Users/dev/.rvm/gems/[email protected]/gems/sshkit-1.5.1/lib/sshkit/backends/netssh.rb:148:in `_execute'
org/jruby/RubyProc.java:271:in `call'

here is my Capfile

require 'capistrano/setup'
require 'capistrano/deploy'

require 'capistrano/rails'
require 'capistrano/bundler'
require 'capistrano/rvm'
require 'capistrano/puma'

Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r }

Deploy.rb

server '192.168.2.6', port: 22, roles: [:app], primary: true

set :repo_url,        '[email protected]:username/appname.git'
set :application,     'appname'
set :user,            'username'
set :puma_threads,    [4, 16]
set :puma_workers,    0
set :shared_children,  []

set :default_env, { rvm_bin_path: '~/.rvm/bin' }
set :default_shell, '/bin/bash -l'
set :pty,             true
set :use_sudo,        false
set :stage,           :staging
set :deploy_via,      :remote_cache
set :deploy_to,       "/var/#{fetch(:application)}"

set :linked_dirs, %w{tmp/pids tmp/sockets log}
set :puma_bind,       "unix:///#{fetch(:deploy_to)}/tmp/sockets/puma.sock"
set :puma_state,      "#{fetch(:deploy_to)}/tmp/pids/puma.state"
set :puma_pid,        "#{fetch(:deploy_to)}/tmp/pids/puma.pid"
set :puma_access_log, "#{fetch(:deploy_to)}/log/puma.error.log"
set :puma_error_log,  "#{fetch(:deploy_to)}/log/puma.access.log"
set :ssh_options,     { forward_agent: true, user: fetch(:user) }
set :puma_preload_app, true
set :puma_worker_timeout, nil
set :puma_init_active_record, false  # Change to true if using ActiveRecord


namespace :puma do
  desc 'Create Directories for Puma Pids and Socket'
  task :make_dirs do
    on roles(:app) do
      execute "mkdir #{shared_path}/tmp/sockets -p"
      execute "mkdir #{shared_path}/tmp/pids -p"
    end
  end

  before :start, :make_dirs
end

namespace :deploy do
  desc "Make sure local git is in sync with remote."
  task :check_revision do
    on roles(:app) do
      unless `git rev-parse HEAD` == `git rev-parse origin/master`
        puts "WARNING: HEAD is not the same as origin/master"
        puts "Run `git push` to sync changes."
        exit
      end
    end
  end

  desc 'Initial Deploy'
  task :initial do
    on roles(:app) do
      before 'deploy:restart', 'puma:start'
      invoke 'deploy'
    end
  end

  desc "Start the application"
  task :start do
    on "[email protected]", in: :sequence, wait: 5  do
      with :rails_env => fetch(:rails_env) do
        execute "cd #{current_path} && /bin/bash -l bundle exec pumactl -F config/puma.rb start"
      end
    end
  end

  before :starting,     :check_revision
  after  :finishing,    :compile_assets
  after  :finishing,    :cleanup
  after  :finishing,    :restart
end

staging.rb

set :stage, :staging
set :branch, 'master'

Gemfile

source 'http://rubygems.org'

gem 'rails', '3.2.8'
gem 'rubyzip', '< 1.0.0'
gem 'roo','1.12.1'
gem 'jdbc-mysql', platform: :jruby
gem 'activerecord-jdbcmysql-adapter', platform: :jruby
gem 'jquery-rails', '2.1.2'

gem 'haml', '3.1.7'
gem 'puma'

gem 'devise', '2.1.2'
gem 'devise-async', '0.5.0'
gem 'cancan', '1.6.8'
gem 'simple_form', '2.0.4'
gem 'cocoon', '1.1.1'
gem 'inherited_resources', '1.3.1'
gem 'will_paginate', '3.0.3'
gem 'bootstrap-will_paginate', '0.0.9'
gem 'mechanize', '2.5.1'
gem 'delayed_job', '3.0.4'
gem 'paperclip', '3.4.0'
gem 'spreadsheet', '0.6.4.1'
gem 'geocoder', '1.1.6'
gem 'whenever', '0.8.2'
gem 'american_date', '1.0.0'
gem 'money','5.1.1'
gem 'rets','0.5.1'
gem 'haversine','0.3.0'

group :assets do
  gem 'stylus', '0.7.1'
  gem 'coffee-rails', '3.2.2'
  gem 'uglifier', '1.3.0'
end

group :development do
  gem 'capistrano',         require: false
  gem 'capistrano-rvm',     require: false
  gem 'capistrano-rails',   require: false
  gem 'capistrano-bundler', require: true
  gem 'capistrano3-puma', github: 'seuros/capistrano-puma',   require: false
end

any advice to help me resolve the problem would be very, very much appreciated.

UPDATED

after editing the code as rubish suggested, now instead I issue the command like this => execute "cd #{current_path} && /bin/bash -l bundle exec pumactl -F config/puma.rb start" now, it get to and is complaining about bundler under global rvm path. The exact new error looks like the following.

DEBUG[df47d6e1] Finished in 0.463 seconds with exit status 0 (successful).
jruby 1.7.16.1 (1.9.3p392) 2014-10-28 4e93f31 on OpenJDK 64-Bit Server VM 1.7.0_65-b32 +jit [linux-amd64]
** Invoke deploy:start (first_time)
** Execute deploy:start
INFO[93744fc5] Running /usr/bin/env cd /var/appname/current && /bin/bash -l bundle exec pumactl -F config/puma.rb start on
 192.168.2.6
DEBUG[93744fc5] Command: cd /var/appname/current && /bin/bash -l bundle exec pumactl -F config/puma.rb start
bind address: 
port: 22
host: 192.168.2.6
options: {:auth_methods=>["none", "publickey", "password", "keyboard-interactive"], :send_env=>[/^LANG$/, /^LC_.*$/], :user=>"root
", :forward_agent=>true, :logger=>#<Logger:0x4c860e93 @logdev=#<Logger::LogDevice:0x7526fc24 @filename=nil, @shift_age=nil, @dev=#
<IO:fd 2>, @mutex=#<Logger::LogDevice::LogDeviceMutex:0x5273db92 @mon_count=0, @mon_mutex=#<Mutex:0x34547888>, @mon_owner=nil>, @s
hift_size=nil>, @formatter=nil, @progname=nil, @default_formatter=#<Logger::Formatter:0x15b5438f @datetime_format=nil>, @level=4>}
DEBUG[93744fc5]         /usr/local/rvm/gems/jruby-1.7.16.1@global/bin/bundle: line 9: require: command not found
DEBUG[93744fc5]         /usr/local/rvm/gems/jruby-1.7.16.1@global/bin/bundle: line 11: version: command not found
DEBUG[93744fc5]         /usr/local/rvm/gems/jruby-1.7.16.1@global/bin/bundle: bundle: line 15: syntax error near unexpected token 
`('
DEBUG[93744fc5]         /usr/local/rvm/gems/jruby-1.7.16.1@global/bin/bundle: bundle: line 15: `  str = str.dup.force_encoding("BI
NARY") if str.respond_to? :force_encoding'
cap aborted!
Exception while executing on host 192.168.2.6: cd /var/appname/current && /bin/bash -l bundle exec pumactl -F config/puma.
rb start exit status: 2
cd /var/appname/current && /bin/bash -l bundle exec pumactl -F config/puma.rb start stdout: Nothing written
cd /var/appname/current && /bin/bash -l bundle exec pumactl -F config/puma.rb start stderr: Nothing written

Upvotes: 0

Views: 1591

Answers (3)

Sachin
Sachin

Reputation: 1003

Try adding the following in your config files(staging.rb, deploy.rb)

set :rvm_map_bins, fetch(:rvm_map_bins).to_a.concat(%w{ puma pumactl })

capistrano-puma gem doesn't always map its bundler with rvm it seems.

Upvotes: 0

rubish
rubish

Reputation: 10907

Generally RVM is initialized only in a login shell, so capistrano commands are unaware of RVM. Simply change your shell command to fix this:

# play nice with rvm
set :default_shell, '/bin/bash -l'

Upvotes: 1

Srdjan Grubor
Srdjan Grubor

Reputation: 2685

So you're pretty much hitting some of the same issues I did when I made my RoR + JRuby + Puma + RVM app. I don't remember all the details but there are a few things that you need to do

1 - I had to use capistrano3-puma from git that was not broken:

gem 'capistrano3-puma', github: 'seuros/capistrano-puma'

2 - Include rails env + path on rake tasks:

 on roles(:db), in: :sequence, wait: 3 do
    within current_path do
      with :rails_env => fetch(:rails_env) do
        rake "some:task"
      end
    end
  end

3 - Finally - and this is the real messed up part since Puma doesn't read~/.bashrc to load RVM paths:

Put the loading of RVM paths in ~/.bash_profile also

There are a number of other things I had to do to get everything working but this should be the big stuff that's not implementation-specific. Also, don't forget to turn Puma into a service or you will have downtime.

Upvotes: 0

Related Questions