Configure unicorn service script using RVM - ruby-on-rails

In my /etc/init.d/unicorn startup script I have the hard-coded paths as follows:
export GEM_HOME=/usr/local/rvm/gems/ruby-2.2.0-dev
export GEM_PATH=/usr/local/rvm/gems/ruby-2.2.0-dev:/usr/local/rvm/gems/ruby-2.2.0-dev/gems:/usr/local/rvm/gems/ruby-2.2.0-dev#global/gems
DAEMON=/usr/local/rvm/gems/ruby-2.2.0-dev/bin/unicorn
UNICORN_OPTS="-D -c /home/unicorn/unicorn.conf -E production"
I am using RVM and when I change the ruby version, then the current ruby should be used for unicorn.
Question 1
So how can I make sure that these variables always point to the proper ruby?
Question 2
In my bundle I am using rack 1.5.5. Now on my production server I had to install the unicorn gem as a "stand-alone-gem" so that I can start my server using:
service unicorn start
Now the unicorn gem installed rack 1.6.x and now my Rails app crashed because rack is already loaded. Now locally I would just execute it with bundle but how can I do that when I am using this /etc/inid.d script.
The part where the server is started looks like follows, and I don't know how I could "inject" the bundler call there or if that is a good practise at all:
# ...
log_daemon_msg "Starting $DESC" $NAME || true
if start-stop-daemon --start --quiet --oknodo --pidfile $PID --exec $DAEMON -- $UNICORN_OPTS; then
The config: /home/unicorn/unicorn.conf
listen "127.0.0.1:8080"
worker_processes 2
user "rails"
working_directory "/home/myapp"
pid "/home/unicorn/pids/unicorn.pid"
stderr_path "/home/unicorn/log/unicorn.log"
stdout_path "/home/unicorn/log/unicorn.log"

Assuming rubyuser has all these rvm and rubies installed, one might parse the output of rvm info, running the latter from this user:
`sudo -H -u rubyuser bash -c '[[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm" && rvm info | grep "^ \+GEM_"| sed -e "s/^ \+/export /" -e "s/: \+/=/"'`
The command above will set the variables GEM_HOME and GEM_PATH. To just output them, remove backticks around this command.
For rvm installed in local, it’s even simpler:
[[ -s "/usr/local/rvm/scripts/rvm" ]] && source "/usr/local/rvm/scripts/rvm" && rvm info | grep "^ \+GEM_"| sed -e "s/^ \+/export /" -e "s/: \+/=/"
# export GEM_HOME="/usr/local/rvm/gems/ruby-2.1.1"
# export GEM_PATH="/usr/local/rvm/gems/ruby-2.1.1:/usr/local/rvm/gems/ruby-2.1.1#global"

Related

start rails from init.d service script and loads the correct version of ruby

I want to start rails server in production mode after installing, migrating and running some scripts in order for this script to be attached as pipeline deploy script.
The problem is that the same script doesn't work as service mode.
ubuntu#ip-x-y-z-w:~/backend.rails.com$ sudo vim /etc/init.d/rails-start-backend
#! /bin/sh
# Start/stop the rails server daemon.
#
### BEGIN INIT INFO
# Provides: rails server start
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start daemon at boot time
# Description: Enable service provided by daemon.
### END INIT INFO
PATH=/bin:/usr/bin:/sbin:/usr/sbin
DESC="rails daemon"
NAME=rails
DAEMON=/home/ubuntu/backend.rails.com/gitlab-ci.sh
PIDFILE=/var/run/rails.pid
test -f $DAEMON || exit 0
. /lib/lsb/init-functions
case "$1" in
start)
log_daemon_msg "Starting rails"
/home/ubuntu/backend.rails.com/gitlab-ci.sh > /home/ubuntu/backend.rails.com/log/start_script.log
start_daemon -p $PIDFILE $DAEMON $EXTRA_OPTS
log_end_msg $?
;;
stop) log_daemon_msg "Stopping rails" "rails"
sudo kill -9 $(sudo lsof -t -i:3000)
killproc -p $PIDFILE $DAEMON
RETVAL=$?
[ $RETVAL -eq 0 ] && [ -e "$PIDFILE" ] && rm -f $PIDFILE
log_end_msg $RETVAL
;;
restart) log_daemon_msg "Restarting " "rails"
$0 stop
$0 start
;;
reload|force-reload) log_daemon_msg "Reloading rails" "rails"
# rails reloads automatically
log_end_msg 0
;;
*) log_action_msg "Usage: /etc/init.d/rails {start|stop|status|restart|reload|force-reload}"
exit 2
;;
esac
exit 0
and thats my gitlab-ci.sh script
cd /home/ubuntu/backend.rails.com
sudo chmod +x gitlab-ci.sh
rm config/master.key
rm config/credentials.yml.enc
echo "credentials"
RAILS_ENV=production EDITOR="mate --wait" rails credentials:edit
export RAILS_ENV=production
export FRONTEND_BASE_URL=https://www.rails.com
echo "bundle install"
bundle install
echo "rails db:migrate"
bundle exec rails db:migrate
echo "rails rake application:initialize"
bundle exec rake application:initialize
echo "kill"
sudo kill -9 $(sudo lsof -t -i:3000)
echo "start"
rails s &
The problem comes when I restarted the sudo service rails-start-backend restart service. It seems that in that context, all bundle, rails and ruby versions and settings are not the same as when I execute the same script manually in ssh.
The errors I get are:
/usr/bin/env: ‘ruby_executable_hooks2.6’: No such file or directory
bundle: not found
here's my PATH when ssh-logged
/home/ubuntu/.rvm/gems/ruby-2.6.5/bin:/home/ubuntu/.rvm/gems/ruby-2.6.5#global/bin:/usr/share/rvm/rubies/ruby-2.6.5/bin:/usr/share/rvm/bin:/home/ubuntu/bin:/home/ubuntu/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
and then when the script is executed as service
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
It works after setting the right paths to the right variables (using 2.6.5 ruby version)
export PATH=/home/ubuntu/.rvm/gems/ruby-2.6.5/bin:/usr/share/rvm/bin:$PATH
export GEM_PATH=/home/ubuntu/.rvm/gems/ruby-2.6.5:/home/ubuntu/.rvm/gems/ruby-2.6.5#global:$GEM_PATH
source .bash_profile
source ~/.rvm/scripts/rvm

Puma Upstart not loading ENV variables

I've deployed an app in production in an Ubuntu Server VM. It uses Puma, so I've followed this guide: https://www.digitalocean.com/community/tutorials/how-to-deploy-a-rails-app-with-puma-and-nginx-on-ubuntu-14-04
to configure it there (it is currently working properly on heroku, we are looking to migrate it to this new server).
This is my /etc/init/puma-manager.conf
# /etc/init/puma-manager.conf - manage a set of Pumas
description "Manages the set of puma processes"
# This starts upon bootup and stops on shutdown
start on runlevel [2345]
stop on runlevel [06]
# Set this to the number of Puma processes you want
# to run on this machine
env PUMA_CONF="/etc/puma.conf"
pre-start script
for i in `cat $PUMA_CONF`; do
app=`echo $i | cut -d , -f 1`
logger -t "puma-manager" "Starting $app"
start puma app=$app
done
end script
And my /etc/init/puma.conf
description "Puma Background Worker"
# no "start on", we don't want to automatically start
stop on (stopping puma-manager or runlevel [06])
# change apps to match your deployment user if you want to use this as a less privileged user (recommended!)
setuid user
setgid user
respawn
respawn limit 3 30
instance ${app}
script
# source ENV variables manually as Upstart doesn't, eg:
. /etc/server-vars
exec /bin/bash <<'EOT'
# set HOME to the setuid user's home, there doesn't seem to be a better, portable way
export HOME="$(eval echo ~$(id -un))"
if [ -d "/usr/local/rbenv/bin" ]; then
export PATH="/usr/local/rbenv/bin:/usr/local/rbenv/shims:$PATH"
elif [ -d "$HOME/.rbenv/bin" ]; then
export PATH="$HOME/.rbenv/bin:$HOME/.rbenv/shims:$PATH"
elif [ -f /etc/profile.d/rvm.sh ]; then
source /etc/profile.d/rvm.sh
elif [ -f /usr/local/rvm/scripts/rvm ]; then
source /etc/profile.d/rvm.sh
elif [ -f "$HOME/.rvm/scripts/rvm" ]; then
source "$HOME/.rvm/scripts/rvm"
elif [ -f /usr/local/share/chruby/chruby.sh ]; then
source /usr/local/share/chruby/chruby.sh
if [ -f /usr/local/share/chruby/auto.sh ]; then
source /usr/local/share/chruby/auto.sh
fi
# if you aren't using auto, set your version here
# chruby 2.0.0
fi
cd $app
logger -t puma "Starting server: $app"
exec bundle exec puma -C config/puma.rb
EOT
end script
It works properly BUT it is not setting the ENV variables I specify in:
/etc/server-vars
I don't want to put all ENV vars directly into this script because they are many, and it limits the usability of the script.
The solution for me was to use "set -a" before sourcing the environment file. Here's the documentation describing what set -a does: The Set Builtin
Try 'set -a' before sourcing your environment file as you can see in the following example:
# /etc/init/puma.conf - Puma config
# This example config should work with Ubuntu 12.04+. It
# allows you to manage multiple Puma instances with
# Upstart, Ubuntu's native service management tool.
#
# See puma-manager.conf for how to manage all Puma instances at once.
#
# Save this config as /etc/init/puma.conf then manage puma with:
# sudo start puma app=PATH_TO_APP
# sudo stop puma app=PATH_TO_APP
# sudo status puma app=PATH_TO_APP
#
# or use the service command:
# sudo service puma {start,stop,restart,status}
#
description "Puma Background Worker"
# no "start on", we don't want to automatically start
start on runlevel [2345]
stop on runlevel [06]
# change apps to match your deployment user if you want to use this as a less privileged user (recommended!)
setuid deploy
setgid deploy
respawn
respawn limit 3 30
instance ${app}
script
# this script runs in /bin/sh by default
# respawn as bash so we can source in rbenv/rvm
# quoted heredoc to tell /bin/sh not to interpret
# variables
# source ENV variables manually as Upstart doesn't, eg:
#. /etc/environment
exec /bin/bash <<'EOT'
set -a
. /etc/environment
# set HOME to the setuid user's home, there doesn't seem to be a better, portable way
export HOME="$(eval echo ~$(id -un))"
if [ -d "/usr/local/rbenv/bin" ]; then
export PATH="/usr/local/rbenv/bin:/usr/local/rbenv/shims:$PATH"
elif [ -d "$HOME/.rbenv/bin" ]; then
export PATH="$HOME/.rbenv/bin:$HOME/.rbenv/shims:$PATH"
elif [ -f /etc/profile.d/rvm.sh ]; then
source /etc/profile.d/rvm.sh
elif [ -f /usr/local/rvm/scripts/rvm ]; then
source /etc/profile.d/rvm.sh
elif [ -f "$HOME/.rvm/scripts/rvm" ]; then
source "$HOME/.rvm/scripts/rvm"
elif [ -f /usr/local/share/chruby/chruby.sh ]; then
source /usr/local/share/chruby/chruby.sh
if [ -f /usr/local/share/chruby/auto.sh ]; then
source /usr/local/share/chruby/auto.sh
fi
# if you aren't using auto, set your version here
# chruby 2.0.0
fi
logger -t puma "Starting server: $app"
cd $app
exec bundle exec puma -C /home/deploy/brilliant/config/puma.rb
EOT
end script

error while running ruby application at system startup in ubuntu

I am on Ubuntu 12.04 machine. Have a script file which runs when entered manually in terminal
gnome-terminal -e /home/precise/Desktop/cartodb/script.sh
The content of script file is
cd /home/ubuntupc/Desktop/cartodb20/
sh /home/ubuntupc/.rvm/scripts/rvm
bundle exec foreman start -p 3000
So what i tried to do is to run this script at every system start up. So on Startup Applications
command: gnome-terminal -e /home/precise/Desktop/cartodb/script.sh
On terminal Edit -> Profile Preferences -> Title and Command
Checked the "Run command as a login shell"
But this seems to be not working. When restarted the machine found these error in terminal
The child process exited normally with status 127.
ERROR: RVM Ruby not used, run `rvm use ruby` first.
Some info regarding the installed packages and system.
$ which ruby
/home/ubuntupc/.rvm/rubies/ruby-1.9.2-p320/bin/ruby
$ which rails
/home/ubuntupc/.rvm/gems/ruby-1.9.2-p320/bin/rails
$ which gem
/home/ubuntupc/.rvm/rubies/ruby-1.9.2-p320/bin/gem
$ cat ~/.bash_profile
[[ -s "$HOME/.profile" ]] && source "$HOME/.profile" # Load the default .profile
[[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm" # Load RVM into a shell session *as a function*
$ which -a ruby
/home/ubuntupc/.rvm/rubies/ruby-1.9.2-p320/bin/ruby
$ sudo update-alternatives --config ruby
update-alternatives: error: no alternatives for ruby.
$ sudo find / -name "rubygems" -print
/home/ubuntupc/.rvm/rubies/ruby-1.9.2-p320/lib/ruby/site_ruby/1.9.1/rubygems
/home/ubuntupc/.rvm/rubies/ruby-1.9.2-p320/lib/ruby/1.9.1/rubygems
/home/ubuntupc/.rvm/src/ruby-1.9.2-p320/lib/rubygems
/home/ubuntupc/.rvm/src/ruby-1.9.2-p320/test/rubygems
/home/ubuntupc/.rvm/src/ruby-1.9.2-p320/test/rubygems/rubygems
/home/ubuntupc/.rvm/src/ruby-1.9.2-p320/doc/rubygems
/home/ubuntupc/.rvm/src/rubygems-2.2.1/lib/rubygems
/home/ubuntupc/.rvm/src/rubygems-2.2.1/test/rubygems
/home/ubuntupc/.rvm/src/rubygems-2.2.1/test/rubygems/rubygems
/home/ubuntupc/.rvm/src/rvm/scripts/functions/rubygems
/home/ubuntupc/.rvm/src/rvm/scripts/rubygems
/home/ubuntupc/.rvm/scripts/functions/rubygems
/home/ubuntupc/.rvm/scripts/rubygems
/usr/lib/ruby/1.9.1/rubygems
/usr/local/rvm/rubies/ruby-1.9.2-p320/lib/ruby/site_ruby/1.9.1/rubygems
/usr/local/rvm/rubies/ruby-1.9.2-p320/lib/ruby/1.9.1/rubygems
/usr/local/rvm/src/ruby-1.9.2-p320/lib/rubygems
/usr/local/rvm/src/ruby-1.9.2-p320/test/rubygems
/usr/local/rvm/src/ruby-1.9.2-p320/test/rubygems/rubygems
/usr/local/rvm/src/ruby-1.9.2-p320/doc/rubygems
/usr/local/rvm/src/rubygems-2.2.0/lib/rubygems
/usr/local/rvm/src/rubygems-2.2.0/test/rubygems
/usr/local/rvm/src/rubygems-2.2.0/test/rubygems/rubygems
/usr/local/rvm/src/rvm/scripts/functions/rubygems
/usr/local/rvm/src/rvm/scripts/rubygems
/usr/local/rvm/scripts/functions/rubygems
/usr/local/rvm/scripts/rubygems
Please point out what i am missing as i am new to the ruby applications.
Thanks in advance

Start Unicorn with Runit and User's RVM

I'm deploying my Rails App servers with Chef. Have just swapped to RVM from a source install of Ruby (because I was having issues with my deploy user).
Now I have my deploy sorted, assets compiled and bundler's installed all my gems.
The problem I have is supervising Unicorn with Runit..
RVM is not installed as root user - only as my deploy user has it, as follows:
$ rvm list
rvm rubies
=* ruby-2.0.0-p247 [ x86_64 ]
I can manually start Unicorn successfully from my deploy user. However, it won't start as part of runit.
My run file looks like this. I have also tried the solution in this SO question unsuccessfully..
#!/bin/bash
cd /var/www/html/deploy/production/current
exec 2>&1
exec chpst -u deploy:deploy /home/deploy/.rvm/gems/ruby-2.0.0-p247/bin/unicorn -E production -c config/unicorn_production.rb
If I run it manually, I get this error:
/usr/bin/env: ruby_noexec_wrapper: No such file or directory
I created a small script (gist here) which does run as root. However, if I call this from runit, I see the workers start but I get two processes for runit and I can't stop or restart the service:
Output of ps:
1001 29062 1 0 00:08 ? 00:00:00 unicorn master -D -E production -c /var/www/html/deploy/production/current/config/unicorn_production.rb
1001 29065 29062 9 00:08 ? 00:00:12 unicorn worker[0] -D -E production -c /var/www/html/deploy/production/current/config/unicorn_production.rb
root 29076 920 0 00:08 ? 00:00:00 su - deploy -c cd /var/www/html/deploy/production/current; export GEM_HOME=/home/deploy/.rvm/gems/ruby-2.0.0-p247; /home/deploy/.rvm/gems/ruby-2.0.0-p247/bin/unicorn -D -E production -c /var/www/html/deploy/production/current/config/unicorn_production.rb
1001 29083 29076 0 00:08 ? 00:00:00 -su -c cd /var/www/html/deploy/production/current; export GEM_HOME=/home/deploy/.rvm/gems/ruby-2.0.0-p247; /home/deploy/.rvm/gems/ruby-2.0.0-p247/bin/unicorn -D -E production -c /var/www/html/deploy/production/current/config/unicorn_production.rb
What should I do here? Move back to monit which worked nicely?
your run file is doing it wrong, you are using the binary without setting the environment, for that purpose you should use wrappers:
rvm wrapper ruby-2.0.0-p247 --no-links unicorn
To simplify the script use alias so it does not need to be changed when you decide which ruby should be used:
rvm alias create my_app_unicorn ruby-2.0.0-p247
And change the script to:
#!/bin/bash
cd /var/www/html/deploy/production/current
exec 2>&1
exec chpst -u deploy:deploy /home/deploy/.rvm/wrappers/my_app_unicorn/unicorn -E production -c config/unicorn_production.rb
This will ensure proper environment is used for execution of unicorn and any time you want change ruby used to run it just crate alias to a new ruby.

Why do I get an error when starting unicorn when the system boots?

This is my init script for unicorn (/etc/init.d/unicorn):
#! /bin/sh
PATH=/home/josue/.rvm/gems/ruby-1.9.3-p0/bin:/home/josue/.rvm/gems/ruby-1.9.3-p0#global/bin:/home/josue/.rvm/rubies/ruby-1.9.3-p0/bin:/home/josue/.rvm/bin:/usr/local/sbin:$
DAEMON=/home/josue/.rvm/gems/ruby-1.9.3-p0/bin/unicorn_rails
DAEMON_OPTS="-c /home/josue/sped/current/unicorn.rb -E production -D"
NAME=unicorn_rails
DESC=unicorn_rails
PID=/home/josue/sped/shared/pids/unicorn.pid
case "$1" in
start)
echo -n "Starting $DESC: "
exec $DAEMON $DAEMON_OPTS
echo "$NAME."
;;
stop)
echo -n "Stopping $DESC: "
kill -QUIT `cat $PID`
echo "$NAME."
;;
restart)
echo -n "Restarting $DESC: "
kill -QUIT `cat $PID`
sleep 1
$DAEMON $DAEMON_OPTS
echo "$NAME."
;;
reload)
echo -n "Reloading $DESC configuration: "
kill -HUP `cat $PID`
echo "$NAME."
;;
*)
echo "Usage: $NAME {start|stop|restart|reload}" >&2
exit 1
;;
esac
exit 0
When I run /etc/init.d/unicorn start logged in as normal user, it works fine, but when I try to run as root, this is the result:
Starting unicorn_rails: /home/josue/.rvm/rubies/ruby-1.9.3-p0/lib/ruby/site_ruby/1.9.1/rubygems/dependency.rb:247:in `to_specs': Could not find unicorn (>= 0) amongst [bigdecimal-1.1.0, io-console-0.3, json-1.5.4, minitest-2.5.1, rake-0.9.2.2, rdoc-3.9.4] (Gem::LoadError)
from /home/josue/.rvm/rubies/ruby-1.9.3-p0/lib/ruby/site_ruby/1.9.1/rubygems/dependency.rb:256:in `to_spec'
from /home/josue/.rvm/rubies/ruby-1.9.3-p0/lib/ruby/site_ruby/1.9.1/rubygems.rb:1210:in `gem'
from /home/josue/.rvm/gems/ruby-1.9.3-p0/bin/unicorn_rails:18:in `<main>'
So, when the server starts, unicorn is not loaded automatically.
I'm using:
ubuntu 10.04
rvm
ruby 1.9.3-p0
There are a few ways to make it work:
Following your code:
PATH=/home/josue/.rvm/gems/ruby-1.9.3-p0/bin:/home/josue/.rvm/gems/ruby-1.9.3-p0#global/bin:/home/josue/.rvm/rubies/ruby-1.9.3-p0/bin:/home/josue/.rvm/bin:$PATH
GEM_HOME=/home/josue/.rvm/gems/ruby-1.9.3-p0
GEM_PATH=/home/josue/.rvm/gems/ruby-1.9.3-p0:/home/josue/.rvm/gems/ruby-1.9.3-p0#global
Using rvm wrappers: https://rvm.io/integration/init-d/
Or others: https://rvm.io/integration/cron/
If you are in a Production environment, you probably don't want to install some of your gems as root, and some other gems get bundled/installed together with the Rails application...
There is an easy way to fix the OPs problem: also set GEM_PATH and GEM_HOME
If you correctly set the PATH, GEM_PATH and GEM_HOME environment variables for the root account (~/.bashrc) , then you will be able to make it work.
e.g. the unicorn executable should be in root's PATH, and the GEM-related env-variables should be set correctly to where the gems are installed during "bundle install" (e.g. this can be in another user's home directory).
$ cat /root/.bashrc
export PATH=/home/josue/.rvm/gems/ruby-1.9.3-p0/bin:/home/josue/.rvm/gems/ruby-1.9.3-p0#global/bin:/home/josue/.rvm/rubies/ruby-1.9.3-p0/bin:/home/josue/.rvm/bin:$PATH
export GEM_HOME=/home/josue/.rvm/gems/ruby-1.9.3-p0/gems
export GEM_PATH=/home/josue/.rvm/gems/ruby-1.9.3-p0/gems:/home/josue/.rvm/gems/ruby-1.9.3-p0#global/gems
After start, you should also touch a file /var/lock/subsys/$APP_NAME
and remove that file after killing the Unicorns , so that your LINUX system knows that your application is running.
This works very well for me in production.
I typically rename the /etc/init.d/unicorn script to the name of my application, in case I have several Apps running.
It seems the Unicorn gem is not installed under root user. Have you tried to login as root and then install it?

Resources