Невозможно запустить службу с помощью sudo, так как пользователь root не имеет доступа к Ruby - PullRequest
3 голосов
/ 12 января 2012

tl; dr
Попытка запустить службу, для работы которой требуется ruby.Но Ruby устанавливается с RVM , где пользователь root не может получить к нему доступ, выдавая ошибку /usr/bin/env: ruby: No such file or directory.rvmsudo не работает.

Фон
У меня есть скрипт init.d, который должен запускать сервер единорога .Я храню сценарий в каталоге config моего приложения rails и символическую ссылку на него с /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

Этот сценарий (добавляемый внизу) по сути просто выполняет следующую команду:

$APP_ROOT/bin/unicorn -D -c $APP_ROOT/config/unicorn.rb -E production

где $APP_ROOT - путь к корню моего приложения rails.Каждый раз, когда эта команда выполняется в этом сценарии init.d, она должна делать это как пользователь dtuite (мое развертывание).Для этого я вызываю su -c "$CMD" - dtuite, а не просто $CMD.

/bin/unicorn - это «бинскрипт», сгенерированный с помощью Bundler , а config/unicorn.rb содержит некоторые параметры конфигурации, которые

Бинскрипт единорога выглядит следующим образом:

#!/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')

Теперь я пытаюсь запустить службу единорога, выполнив:

sudo service busables_unicorn start

Однако это приводит к ошибке:

/usr/bin/env: ruby: No such file or directory

Я полагаю, что это происходит, потому что я запускаю службу от имени пользователя root, но RVM установил ruby ​​в домашнем каталоге пользователя dtuite, а пользователь rootнет доступа к нему.

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:$

Вопрос
Что мне нужно сделать, чтобы сделать эту работу?

Моя настройка
- ubuntu 11.10
- ruby ​​1.9.3p0 (версия 2011-10-30 33570) [i686-linux]
- nginx: версия nginx: nginx / 1.0.5

Что я пробовал

rvmsudo

$ rvmsudo service busables_unicorn start
/usr/bin/env: ruby: No such file or directory

rvm-auto-ruby

$ 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

Это другой вопрос может помочь, но, если честно, я не совсем понимаю.

Приложение
Сценарий busables_unicorn полностью.

# 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

Ответы [ 2 ]

2 голосов
/ 12 января 2012

Похоже, что su не порождает оболочку, которая читает файлы профиля, которые обычно устанавливают среду rvm.

Я бы попробовал изменить команду, которую вы запускаете, на

 source "/home/dtuite/.rvm/scripts/rvm" && $APP_ROOT/bin/unicorn...
1 голос
/ 12 января 2012

Попробуйте добавить свой путь ruby ​​где-нибудь в начале сценария запуска, в таком выражении экспорта, как это:

export PATH=/home/dtuite/.rvm/rubies/ruby-1.9.3-p0/bin:$PATH

...