I'm following a tutorial at DigitalOcean (fyi, this is the tutorials, link1 , link2 ), to install a production ready rails app using unicorn, and nginx, and when I get to the part on installing unicorn. When I try typing this into the console:
sudo service unicorn_appname start
I get this error:
Starting appname
-su: bundle: command not found
All users can bundle. This message makes no sense to me. Any ideas?
I also followed the same guide and had the same issue.
The startup script in init.d/unicorn_appname is evaluated to:
su - deploy -c cd /home/deploy/appname && bundle exec unicorn -c config/unicorn.rb -E production -D
root user on startup will first su - into the rails user (in this case 'deploy') then excutes bundle to start up unicorn. rbenv is single user, only 'deploy' has bundle installed. The path to bundle is likely stored in your .bashrc file if you followed the guide. However .bashrc file which is not invoked by login in through su - and that caused the bundle not installed error.
The solution would be to include the paths related to rbenv in .profile. This way when root su - into 'deploy' the paths are loaded.
You can fix this by adding the rbenv shims path to your .profile
cd ~
vi .profile
look for the line that starts with PATH="
just after the quote add the following:
$HOME/.rbenv/shims:
save the file ( ESC :wq )
start the service as you normally would.
Looks like you starting service with "system wide Ruby /usr/bin/ruby" which doesn't have gem "bundler" installed yet, not with version of Ruby which you expecting to be in runtime (installed through the RVM or RBENV somewhere in user namespace). Make sure desired Ruby version infrastructure is in the path prior to call "bundle exec unicorn...".
Part of my unicorn_service script:
USER="ubuntu"
APP_NAME="my_app_name"
APP_ROOT="/home/$USER/$APP_NAME"
ENV="production"
# environment settings
PATH="/home/$USER/.rbenv/shims:/home/$USER/.rbenv/bin:$PATH"
When I ran sudo service unicorn start I got the same error i.e bundle command not found.
Initially, path was present in my .bashrc file.
export PATH="$HOME/.rbenv/bin:$PATH"
eval "$(rbenv init -)"
Adding the path in .bash_profile did the work for me. I guess it is taking $PATH from .bash_profile not from .bashrc.
After copying this path to .bash_profile and then doing source .bash_profile worked for me.
Related
I have a rails site, which I deploy via ssh using a git post-receive hook. When I ssh into the server and run bundle install it runs correctly under the specified ruby version of 2.2.2. However, when I push to the server from my local machine and it hits the 'bundle install command', I get the following:
hooks/post-receive: /usr/local/bin/bundle: /usr/bin/ruby1.9.1: bad interpreter: No such file or directory
I can't find for the life of me why it is pointing to ruby1.9.1. This directory does not exist. I do see a directory for ruby2.3 in that directory, but not ruby2.2.2 which is the correct directory. Something is quite fouled up, but I can't figure how to fix it. Anyone seen anything like this?
UPDATE: Here is my post-receive hook, as per the request below...
#!/bin/bash
GIT_DIR=/home/deploy/www_production
WORK_TREE=/home/deploy/www
export MGOTS_DATABASE_USER='user'
export MGOTS_DATABASE_PASSWORD='pass'
export RAILS_ENV="production"
. ~/.bash_profile
while read oldrev newrev ref
do
if [[ $ref = refs/heads/master ]];
then
echo "Master ref received. Deploying master branch to production..."
mkdir -p $WORK_TREE
git --work-tree=$WORK_TREE --git-dir=$GIT_DIR checkout -f
mkdir -p $WORK_TREE/shared/pids $WORK_TREE/shared/sockets $WORK_TREE/shared/log
# start deploy tasks
cd $WORK_TREE
bundle install
rake db:create
rake db:migrate
rake assets:precompile
rake requests:cleanup
sudo restart puma-manager
sudo service nginx restart
# end deploy tasks
echo "Git hooks deploy complete"
else
echo "Ref $ref successfully received. Doing nothing: only the master branch may be deployed on this server."
fi
done
UPDATE: For the sake of clarity, as the answer points to the correct place to find the answer, but doesn't state it exactly, I am posting my updated hook file here. You can see the difference between this one and the one above, and that is what solved the problem. Please note that the path to the rvm directory can be found by typing the command: which rvm - that's the one you want to point to.
#!/bin/bash
GIT_DIR=/home/deploy/www_production
WORK_TREE=/home/deploy/www
export MGOTS_DATABASE_USER='user'
export MGOTS_DATABASE_PASSWORD='pass'
export RAILS_ENV="production"
export RUBYGEMS_GEMDEPS="/home/deploy/.rvm/ruby-2.2.2#www/gems"
. ~/.bash_profile
[[ -s "/usr/share/rvm/bin/rvm" ]] && source "/usr/share/rvm/bin/rvm"
while read oldrev newrev ref
do
if [[ $ref = refs/heads/master ]];
then
echo "Master ref received. Deploying master branch to production..."
mkdir -p $WORK_TREE
git --work-tree=$WORK_TREE --git-dir=$GIT_DIR checkout -f
mkdir -p $WORK_TREE/shared/pids $WORK_TREE/shared/sockets $WORK_TREE/shared/log
# start deploy tasks
cd $WORK_TREE
bundle install
rake db:create
rake db:migrate
rake assets:precompile
rake requests:cleanup
sudo restart puma-manager
sudo service nginx restart
# end deploy tasks
echo "Git hooks deploy complete"
else
echo "Ref $ref successfully received. Doing nothing: only the master branch may be deployed on this server."
fi
done
You need to load RVM functions to the shell script. link
Or just switch to Rbenv :)
First, set your default ruby to use the version 2.2.2
Are you using RVM? For RVM its: rvm use --default 2.2.2
When I execute this command:
/usr/local/bin/bundle exec rails runner -e production "load 'job_alerta_validacao.rb'"
It returns:
Could not locate Gemfile
How can I set where the application is directly in the command without needing to create a script with the "cd" command?
The most common way to use bundler is to cd to the directory containing the Gemfile. This is also the most robust way, since some other gems will probably assume that the working directory is the root of the Rails project.
If you just don't want to change your current shell's working directory, cd in a subshell:
(cd /some/directory; /usr/local/bin/bundle exec rails runner -e production "load 'job_alerta_validacao.rb'")
If you really want to execute something through bundler with a working directory other than the directory with the Gemfile, tell bundler where to find the Gemfile with the BUNDLE_GEMFILE environment variable:
BUNDLE_GEMFILE=/some/directory/Gemfile /usr/local/bin/bundle exec rails runner -e production "load 'job_alerta_validacao.rb'"
I'm trying to start the rails app when Ubuntu starts up.
For this, I added these lines in /etc/rc.local.
cd /home/ubuntu/webapp/rails/passenger-ruby-rails-demo
bundle exec passenger start --port 8000 --user ubuntu --daemonize
However, the rc.local exits with error
+ cd /home/ubuntu/webapp/rails/passenger-ruby-rails-demo
+ bundle exec passenger start --port 8000 --user ubuntu --daemonize
/usr/lib/ruby/vendor_ruby/bundler/spec_set.rb:92:in `block in materialize': Could not find rake-10.4.2 in any of the sources (Bundler::GemNotFound)
from /usr/lib/ruby/vendor_ruby/bundler/spec_set.rb:85:in `map!'
from /usr/lib/ruby/vendor_ruby/bundler/spec_set.rb:85:in `materialize'
from /usr/lib/ruby/vendor_ruby/bundler/definition.rb:114:in `specs'
from /usr/lib/ruby/vendor_ruby/bundler/definition.rb:159:in `specs_for'
from /usr/lib/ruby/vendor_ruby/bundler/definition.rb:148:in `requested_specs'
from /usr/lib/ruby/vendor_ruby/bundler/environment.rb:18:in `requested_specs'
from /usr/lib/ruby/vendor_ruby/bundler/runtime.rb:13:in `setup'
from /usr/lib/ruby/vendor_ruby/bundler.rb:120:in `setup'
from /usr/lib/ruby/vendor_ruby/bundler/setup.rb:17:in `<top (required)>'
from /usr/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
from /usr/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
The error is caused from using the ruby installed from rbenv; the ruby is in /home/ubuntu/.rbenv/bin/ directory. I guess when ubuntu starts up, the system ruby is executed, but it does not know anything about installed packges with rbenv's ruby and gem.
How can I solve this issue? Is there any way to make the ruby from rbenv as system's ruby?
For getting the error, I used the hints from this post: Run script with rc.local: script works, but not at boot.
EDIT
mwp's answer works fine, but I think I'd better make things clearer.
development bundle
Run bundle --deployment --binstubs to create ./vendor and copy files in bundle directory.
The setup.sh
#!/bin/bash
export APP_ROOT="/home/ubuntu/webapp/rails/passenger-ruby-rails-demo"
export APP_USER="ubuntu"
export APP_PORT="8000"
export RBENV_ROOT="/home/ubuntu/.rbenv"
export PATH="$RBENV_ROOT/bin:$PATH"
eval "$(rbenv init -)"
# Assuming you installed bundle with --binstubs...
$APP_ROOT/bin/passenger start --port $APP_PORT --user $APP_USER --daemonize
The rc.local file
cd /home/ubuntu/webapp/rails/passenger-ruby-rails-demo
sh ./setup.sh
exit 0
Run these commands one time:
cd /home/ubuntu/webapp/rails/passenger-ruby-rails-demo
rbenv local <the version you want>
This will create a .ruby-version file in your application directory that tells rbenv which version to use.
I would also recommend that when you deploy the application to its "production" location, you install bundler with the --deployment --binstubs flags. This will install the Gems inside a vendor subdirectory (to insulate them from an errant Gem update) and create handy shortcuts inside a bin subdirectory to run e.g. passenger, rackup, etc. without needing to do bundle exec.
However, you have another problem, and that is that rbenv (the shell function) [probably] isn't available while rc.local is running. I would recommend creating a new shell script and stashing it somewhere, possibly within your application's directory structure, with (something like) the following contents:
#!/bin/bash
export APP_ROOT="/home/ubuntu/webapp/rails/passenger-ruby-rails-demo"
export APP_USER="ubuntu"
export APP_PORT="8000"
export RBENV_ROOT="/path/to/rbenv"
export PATH="$RBENV_ROOT/bin:$PATH"
eval "$(rbenv init -)"
# Assuming you installed bundle with --binstubs...
"$APP_ROOT"/bin/passenger start --port $APP_PORT --user $APP_USER --daemonize
Then mark this script executable and you can call it from rc.local to start the service. As far as what you set RBENV_ROOT to, you can either use an existing user's .rbenv directory (e.g. ~ubuntu/.rbenv, assuming you installed a copy there), or you can set up a system-wide rbenv at /opt/rbenv or elsewhere. There are some good notes here.
I can think of a million different ways to improve the above script, and indeed this is only one of a million different ways to tackle this problem. Starting and stopping services is quite a hot topic in the DevOps and SysAdmin communities right now. I've had great success running Ruby applications in production using rbenv and Bundler, and if you decide to go this route, I hope you will too!
Upstart (http://upstart.ubuntu.com) can be a better way to replace rc.local.
# simple script
# http://uwsgi-docs.readthedocs.org/en/latest/Upstart.html
description "passenger "
start on runlevel [2345]
stop on runlevel [06]
respawn
# http://stackoverflow.com/questions/14823972/upstart-node-js-working-directory
script
chdir /home/ubuntu/webapp/rails/passenger-ruby-rails-demo
exec sh runme.sh
end script
If you have simple shell command binstubs in the local bin directory of a Rails project (e.g. not generated by or running a gem), rbenv seems to have trouble executing them. For example, #tpope's heroku binstubs generate a binstub named production in the local bin directory:
#!/bin/sh
HEROKU_APP=myapp-production HKAPP=myapp-production exec "${HEROKU_COMMAND:-heroku}" "$#"
After an rbenv rehash, the production command shows up in the ~/.rbenv/shims directory looking something like this:
#!/usr/bin/env bash
set -e
[ -n "$RBENV_DEBUG" ] && set -x
program="${0##*/}"
if [ "$program" = "ruby" ]; then
for arg; do
case "$arg" in
-e* | -- ) break ;;
*/* )
if [ -f "$arg" ]; then
export RBENV_DIR="${arg%/*}"
break
fi
;;
esac
done
fi
export RBENV_ROOT="/Users/Username/.rbenv"
exec "/usr/local/Cellar/rbenv/0.4.0/libexec/rbenv" exec "$program" "$#"
So executing which production gives you:
/Users/Username/.rbenv/shims/production
But executing rbenv which production (or trying to run the command) gives you:
rbenv: production: command not found
I'm new to rbenv so maybe I missed a config step?
Apparently project-specific binstubs in Rails projects should be kept outside of the local bin/ directory since those are primarily for application scripts. So one approach (i.e. that used by the rbenv-binstubs plugin) is to keep local binstubs separate and override rbenv shims with that local binstub directory (e.g. .bundle/bin). So by using the plugin you might see this result from which production:
/Users/Username/.rbenv/shims/production
But if you move the production binstub to .bundle/bin, then rbenv which production should yield:
{PROJECT_ROOT}/.bundle/bin/production
I am using RVM environment. RUby version : 2.1.2 rails : 4.1.1
schedule.rb :
every 1.minute do
runner "note.send_mail"
end
I used whenever --update-crontab to update the cron tab.
when I check the jobs using crontab -l it shows up as below with no proper time set up.
and the cron job does not work.
* * * * * /bin/bash -l -c 'cd /Desktop/folder1/blog2 && bin/rails runner -e production '\''note.send_mail'\'''
Can some one help me out fix this. Thanks!
Go to your ~/.rvmrc file and add the following:
rvm_trust_rvmrcs_flag=1
Then whenever --update-crontab again. According to the README of whenever:
If your production environment uses RVM (Ruby Version Manager) you will run into a gotcha that causes your cron jobs to hang. This is not directly related to Whenever, and can be tricky to debug. Your .rvmrc files must be trusted or else the cron jobs will hang waiting for the file to be trusted. A solution is to disable the prompt by adding this line to your user rvm file in ~/.rvmrc
rvm_trust_rvmrcs_flag=1
This tells rvm to trust all rvmrc files.
If that doesn't work for you, try other solutions mentioned in this page: RVM-Notes.
You could define a custom runner that loads rvm on the command line, like
job_type :runner_with_rvm, 'source /etc/profile.d/rvm.sh; cd :path;rvm 2.0#gemset do bundle exec script/rails runner -e :environment ':task' :output'
every 1.minute do
runner_with_rvm "Note.send_email"
end
Replace 2.0#gemset with your desired ruby version and gemset.
Could be that /etc/profile.d/rvm.sh is something else in your environment too.