tl;dr
Trying to run a service which needs ruby to run. But, Ruby is installed with RVM where the root user can't seem to access it, producting the error /usr/bin/env: ruby: No such file or directory
. rvmsudo
doesn't work.
Background
I have an init.d
script which is supposed to start a unicorn server. I keep the script in the config
directory of my rails application and symlink to it from /etc/init.d/busables_unicorn
.
$ ls -l /etc/init.d/busables_unicorn
-> lrwxrwxrwx 1 root root 62 2012-01-12 15:02 busables_unicorn -> /home/dtuite/dev/rails/busables/current/config/unicorn_init.sh
This script (which is appended to the bottom) essentially just runs the following command:
$APP_ROOT/bin/unicorn -D -c $APP_ROOT/config/unicorn.rb -E production
where $APP_ROOT
is the path to the root of my rails application. Every time that command is executed in that init.d script, it is supposed to do so as the dtuite
(my deploy) user. To accomplish that, I call su -c "$CMD" - dtuite
rather than just $CMD
.
/bin/unicorn
is a "binscript" which was generated by Bundler and config/unicorn.rb
contains some configuration options which are passed to it.
The unicorn binscript looks like this:
#!/usr/bin/env ruby
#
# This file was generated by Bundler.
#
# The application 'unicorn' is installed as part of a gem, and
# this file is here to facilitate running it.
#
require 'pathname'
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
Pathname.new(__FILE__).realpath)
require 'rubygems'
require 'bundler/setup'
load Gem.bin_path('unicorn', 'unicorn')
Now, I'm trying to start my unicorn service by running:
sudo service busables_unicorn start
That however produces the error:
/usr/bin/env: ruby: No such file or directory
I believe that this is happening because I'm running the service as the root user but RVM has installed ruby under the dtuite
user's home directory and the root user has no access to it.
dtuite@localhost:$ which ruby
-> /home/dtuite/.rvm/rubies/ruby-1.9.3-p0/bin/ruby
dtuite@localhost:$ su
Password:
root@localhost:$ which ruby
root@localhost:$
Question
What do I need to do to make this work?
My Setup
- ubuntu 11.10
- ruby 1.9.3p0 (2011-10-30 revision 33570) [i686-linux]
- nginx: nginx version: nginx/1.0.5
What I've tried
$ rvmsudo service busables_unicorn start
/usr/bin/env: ruby: No such file or directory
$ sudo service cakes_unicorn start
-> [sudo] password for dtuite:
-> -su: /home/dtuite/dev/rails/cakes/current/bin/unicorn: rvm-auto-ruby: bad interpreter: No such file or directory
This other question may help but to be honest I don't really understand it.
Appendix
The busables_unicorn
script in it's entirety.
# INFO: This file is based on the example found at
# https://github.com/defunkt/unicorn/blob/master/examples/init.sh
# Modifications are courtesy of Ryan Bate's Unicorn Railscast
# Install Instructions:
# sudo ln -s full-path-to-script /etc/init.d/APP_NAME_unicorn
# Once installed, an app's unicorn can be reloaded by running
# sudo service APP_NAME_unicorn restart
#!/bin/sh
set -e
# Example init script, this can be used with nginx, too,
# since nginx and unicorn accept the same signals
# Feel free to change any of the following variables for your app:
TIMEOUT=${TIMEOUT-60}
APP_ROOT=/home/dtuite/dev/rails/busables/current
PID=$APP_ROOT/tmp/pids/unicorn.pid
# in order to access this, we need to first run
# 'bundle install --binstubs'. THis will fill our
# app/bin directory with loads of stubs for executables
# this is the command that is run when we run this script
CMD="$APP_ROOT/bin/unicorn -D -c $APP_ROOT/config/unicorn.rb -E production"
# we don't need an init config because this file does it's job
action="$1"
set -u
old_pid="$PID.oldbin"
cd $APP_ROOT || exit 1
sig () {
test -s "$PID" && kill -$1 `cat $PID`
}
oldsig () {
test -s $old_pid && kill -$1 `cat $old_pid`
}
case $action in
start)
sig 0 && echo >&2 "Already running" && exit 0
# NOTE: We have to change all these lines.
# Otherwise, the app will run as the root user
su -c "$CMD" - dtuite
;;
stop)
sig QUIT && exit 0
echo >&2 "Not running"
;;
force-stop)
sig TERM && exit 0
echo >&2 "Not running"
;;
restart|reload)
sig HUP && echo reloaded OK && exit 0
echo >&2 "Couldn't reload, starting '$CMD' instead"
su -c "$CMD" - dtuite
;;
upgrade)
if sig USR2 && sleep 2 && sig 0 && oldsig QUIT
then
n=$TIMEOUT
while test -s $old_pid && test $n -ge 0
do
printf '.' && sleep 1 && n=$(( $n - 1 ))
done
echo
if test $n -lt 0 && test -s $old_pid
then
echo >&2 "$old_pid still exists after $TIMEOUT seconds"
exit 1
fi
exit 0
fi
echo >&2 "Couldn't upgrade, starting '$CMD' instead"
su -c "$CMD" - dtuite
;;
reopen-logs)
sig USR1
;;
*)
echo >&2 "Usage: $0 <start|stop|restart|upgrade|force-stop|reopen-logs>"
exit 1
;;
esac