Search code examples
ruby-on-railsrubydeploymentunicornrbenv

Why is su using a different ruby version compared to when I'm logged in as the actual user?


I'm trying to deploy a Ruby on Rails application using nginx and unicorn. When I try to run my unicorn init script, I get the following error:

$ sudo service rails_app start
Starting rails_app
-su: bundle: command not found

It fails to run on this command:

su - complab -c "bundle exec unicorn -c config/unicorn.rb -E production -D"

However, running unicorn manually while logged in as $USER works just fine:

$ bundle exec unicorn -c config/unicorn.rb -E production

I have verified that the path set on the init script is correct. On further investigation, I discovered that while $USER has ruby version 2.2.0 installed via rbenv, running su - $USER -c "ruby -v" shows that it's running on 1.9.3.

I have already run rbenv global 2.2.0 but still it doesn't work.

I thought su meant I was able to temporarily changing the user who owns the session? Why is it that su $USER shows a different ruby version from when I am actually logged in as $USER?

Hope you can help me out!


Solution

  • The reason is that sudo doesn't preserve environment variable. And since rbenv is using user environment it doesn't work out of the box. You can use a command like this to run ruby with sudo:

    ruby=`which ruby` && sudo $ruby -v
    

    If you want to run unicorn under the user you have installed rbenv into you have to change these to match your app:

    !/bin/sh
    
    ### BEGIN INIT INFO
    # Provides:          unicorn
    # Required-Start:    $local_fs $remote_fs
    # Required-Stop:     $local_fs $remote_fs
    # Default-Start:     2 3 4 5
    # Default-Stop:      0 1 6
    # Short-Description: starts unicorn
    # Description:       starts uniconr using start-stop-daemon
    ### END INIT INFO
    
    set -u
    set -e
    
    export PATH=/path/to/rbenv/bin:$PATH
    export RBENV_DIR=/path/to/rbenv
    export RBENV_ROOT=/path/to/rbenv
    
    APP_ROOT=/path/to/rack_app/root
    PID=$APP_ROOT/tmp/pids/unicorn.pid
    RAILS_ENV=production
    
    export PATH="$RBENV_ROOT/shims:$RBENV_ROOT/rbenv:$PATH"
    CMD="bundle exec $RBENV_ROOT/shims/unicorn -D -E $RAILS_ENV -c config/unicorn/$RAILS_ENV.rb"
    
    
    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 $1 in
    start)
        sig 0 && echo >&2 "Already running" && exit 0
        $CMD
        ;;
    stop)
        sig QUIT && exit 0
        echo >&2 "Not running"
        ;;
    force-stop)
        sig TERM && 0
        echo >&2 "Not running"
        ;;
    restart|reload)
        sig HUP && echo reloaded OK && exit 0
        echo >&2 "Couldn't reload, starting '$CMD' instead"
        $CMD
        ;;
    upgrade)
        sig USR2 && exit 0
        echo >&2 "Couldn't upgrade, starting '$CMD' instead"
        ;;
    rotate)
        sig USR1 && echo rotated logs OK && exit 0
        echo >&2 "Couldn't rotate logs" && 1
        ;;
    *)
        echo >&2 "Usage $0 <start|stop|restart|upgrade|rotate|force-stop>"
        exit 1
        ;;
    esac