Ruby RVM under another user from Bash script - ruby

What is the best way to launch ruby script under another user via su command and from another script?
I have a bash script with the following command for launching unicorn:
sudo -u unicornuser sh -l -c "bundle exec unicorn_rails -E production -D"
This script is an init.d script and it being execute when system starts and manually also.
The problem is the default ruby on system is 1.8, other rubyes (1.9) is working under RVM. I need to modify above script that it can execute ruby with RVM (non system wide)
Now I've migrated for this notation:
su -l -c "rvm use ruby-1.9.3-p125 && bundle exec unicorn_rails -E production -D" unicornuser
this worked for me, but I guess there must be a better way to do this.

You should use wrappers:
rvm wrapper ruby-1.9.3-p125 ext_1.9.3 bundle
This will create $rvm_path/bin/ext_1.9.3_bundle, so now you can use:
/full/path/to/rvm/bin/ext_1.9.3_bundle exec unicorn_rails -E production -D
replace /full/path/to/rvm with output from echo $rvm_path

Related

Ubuntu start up Rails on boot up

I want to start my Rails server with the following command on boot up:
cd /home/ubuntu/app && bundle exec rails server -p 8080 -e production
I placed it inside the /etc/rc.local, but it never starts up the server. If I remove bundle exec then shell complains about not finding the rails command.
Both variants, with and without bundle exec, work if I log in, and execute it manually.
I am totally lost. Any suggestions?
Try to change a user
su ubuntu && cd /home/ubuntu/app && bundle exec rails server -p 8080 -e production
Running your script as root is not a good idea, so you want to change user before starting your code.
su is indeed the command you want to use, but you need to realise that all arguments are passed to the login shell. So the following won't work (assuming fofox is your username):
su fofox pwd
as you're effectively saying
/bin/bash /bin/pwd
but /bin/pwd does not contain a list of shell commands, so both will give an error message:
/bin/pwd: /bin/pwd: cannot execute binary file
Thus you need to add something to the shell saying you're passing a list of commands, like this:
/bin/bash -c /bin/pwd
The last wrinkle is that you want to pass a number of arguments to the su command but protect them from the shell, as
su fofox -c id && id
will show you that the first bit is executed as fofox and the second part as root again. Single quotes are used to prevent the root shell to see the && characters.
So the final command becomes:
su fofox -c 'cd /home/ubuntu/app && bundle exec rails server -p 8080 -e production'

Why is sudo: bundle command not found?

Why is command "bundle" not found when using sudo:
[root#desktop gitlab]# sudo -u git -H bundle exec rake gitlab:setup RAILS_ENV=production
sudo: bundle: command not found
[root#desktop gitlab]#
but does exist when not using sudo:
[root#desktop gitlab]# bundle exec rake gitlab:setup RAILS_ENV=production
Warning
You are running as user root, we hope you know what you are doing.
Things may work/fail for the wrong reasons.
For correct results you should run this as user git.
This will create the necessary database tables and seed the database.
You will lose any previous data stored in the database.
Do you want to continue (yes/no)? no
Quitting...
[root#desktop gitlab]#
The reason I ask is I am following https://github.com/gitlabhq/gitlab-recipes/tree/master/install/centos, and it states to use sudo.
I've tried adding a -i flag as described by Using $ sudo bundle exec ... raises 'bundle: command not found' error, but get "This account is currently not available.".
Check if the PATH has the same values both with and without sudo. Apparently it cannot find bundle just because it is not listed in PATH
You can compare the outputs of following two lines
$ echo 'echo $PATH' | sh
$ echo 'echo $PATH' | sudo sh
Ideally sudo is supposed to leave PATH untouched. But this might be a side issue of your hosting distribution.
Edit by original poster. Output is:
[root#desktop etc]# echo 'echo $PATH' | sh
/usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
[root#desktop etc]# echo 'echo $PATH' | sudo sh
/sbin:/bin:/usr/sbin:/usr/bin:/user/local/bin
[root#desktop etc]#
The user was created without a bash login shell. Change this in centos using system-config-users. Then su git into /home/git and move to gitlab directory. Execute the bundle commands without the sudo tag. The next error you will encounter is the missing database.yml in the config dir. fix this with the correct password (i.e. copy the mysql or postgres sample and edit).
I had this issue I thought that my gitlab installed from source and I got same error. but after try Omnibus method for backup my issue solved
with this command:
sudo gitlab-rake gitlab:backup:create
Try :
sudo -u git -H env PATH=$PATH && bundle exec rake gitlab:check RAILS_ENV=production
to use the same PATH than current user.

Why does ruby script stop when trying to start unicorn_rails as daemon?

I'm trying to start unicorn_rails in a ruby script, and after executing many commands in the script, when the script gets to the following line
%x[bash -ic "bash <(. ~/.bashrc); cd /home/www-data/rails_app; bundle exec unicorn_rails -p 8000 -E production -c /home/www-data/rails_app/config/unicorn.rb -D"]
the script stops, generating the following output
[1]+ Stopped ./setup_rails.rb
and returns to the Linux prompt. If I type "fg", the script finishes running, the line where the script had stopped gets executed and unicorn gets started as a daemon.
If I run the line in a separate script, the script completes without stopping.
UPDATE_1 -
I source .bashrc because earlier in the script I install rvm and to get it to run with the correct environment I have the following:
%x[echo "[[ -s \"$HOME/.rvm/scripts/rvm\" ]] && source \"$HOME/.rvm/scripts/rvm\"" >> .bashrc]
%x[bash -ic "bash <(. ~/.bashrc); rvm install ruby-1.9.2-p290; rvm 1.9.2-p290 --default;"]
So if I want to run correct version of rvm, ruby and bundle I need to source .bashrc
end UPDATE_1
Does anyone have any idea what could cause a ruby script to halt as if control-Z was pressed?
Not sure why it's stopping, but my general rule of thumb is to never source my .bashrc in a script -- that might be the source of your problem right there, but I can't be sure without seeing what's in it. You should be able to change your script to something like:
$ vi setup_rails.sh
#!/usr/bin/bash
# EDIT from comments below
# expanding from a one liner to a better script...
$RVM_PATH=$HOME/.rvm/scripts
# install 1.9.2-p290 unless it's installed
$RVM_PATH/rvm info 1.9.2-p290 2&>1 >/dev/null || $RVM_SH install 1.9.2-p290
# run startup command inside rvm shell
$RVM_PATH/rvm-shell 1.9.2-p290 -c "cd /home/www-data/rails_app && bundle exec unicorn_rails -p 8000 -E production -c /home/www-data/rails_app/config/unicorn.rb -D"
This should give you the same result.

Run a gem from rvm with runit

I need to create a runit service that runs a gem's binary that was installed with rvm, the problem is that a non-login bash shell, which is how runit runs its services does not have the correct path's for rvm. Is there any automatic way of doing this?
I use following script:
#!/bin/sh
exec 2>&1
DIR=/var/www/apps/mega_app/current
export rvm_path=/usr/local/rvm
export rvm_ignore_rvmrc=1
cd $DIR
exec chpst -u user:group /usr/local/rvm/bin/rvm ree exec bundle exec ${DIR}/daemons/mega_daemon.rb
Does su - USERNAME -c '/path/to/script' work? It should preserve the $PATH variables.

Problem deploying Ruby+RVM and daemontools

I am using daemontools in production to keep the services alive and want to run a Ruby server, not Rails, and without RVM it works well but with RVM I have some issues.
My goal is to start a process by root, make it drop root rights to get another user rights and then spawn a Ruby process with RVM and a specified Ruby version.
Here is the run script I was using until now:
#!/bin/sh
exec 2>&1
cd /app/src
. /usr/local/rvm/scripts/rvm
rvm use 1.9.1-p378
exec setuidgid app_user ruby main.rb
This script works but setuidgid has a major problem: the application will be run by user <x> and group <x> and only this group. If the user is in other groups the process will not have their rights.
So it led me to another approach:
#!/bin/sh
exec 2>&1
cd /app
exec sudo -u app_user rvm 1.9.1-p378 exec ruby main.rb
This one works fine except it is the RVM process which is spawned by daemontools and it does not react when it receives a SIGTERM which is not really nice. Basically it means the service cannot be restarted by hand, which is not good.
I found the answer but looking at the rvmsudo script installed with rvm, here is a working run script:
#!/bin/sh
# redirect stderr to stdout
exec 2>&1
cd /app
# load rvm
. /usr/local/rvm/scripts/rvm
# select ruby version for this application
rvm use 1.9.1
# # depending on your configuration you may need to provide the absolute path to rvm, like that:
# /usr/local/bin/rvm use 1.9.1
# build the exec command line preserving the rvm environment
command="exec sudo -u app_user /usr/bin/env PATH='$PATH'"
[[ -n "${GEM_HOME:-}" ]] && command="${command} GEM_HOME='$GEM_HOME' "
[[ -n "${GEM_PATH:-}" ]] && command="${command} GEM_PATH='$GEM_PATH' "
# this is where your real command line goes
command="${command} ruby main.rb"
# run the application
eval "${command}"

Resources