5

I used foreman to export my Procfile to an upstart task.

Procfile:

web: bundle exec rails server
websocket: bundle exec rails runner websocket-server/em_websocket.rb

One of the upstart tasks (they are very alike and fail with the same error):

start on starting app-web
stop on stopping app-web
respawn

env PORT=5000

setuid app

chdir /var/www/app

exec bundle exec rails server

And the error (I got it via dmesg):

[35207.676836] init: Failed to spawn app-websocket-1 main process: unable to execute: No such file or directory
[35207.679577] init: Failed to spawn app-web-1 main process: unable to execute: No such file or directory

When I switch to the app user, I am actually able to run bundle exec rails server from the given directory.

Is there any way to pin down the error a little more? I didn't find any related logs in /var/log/upstart/.

Gregor Weber
  • 690
  • 9
  • 24

3 Answers3

5

If you installed ruby via RVM it may be possible that the init is run before the rvm script runs. Did you try using absolute references to the bundle bin?

whereis bundle 

to obtain it

RVM was apparently not initialized or is not available in the upstart enviroment. Luckily rvm has wrappers for this case: https://rvm.io/integration/init-d

Gregor Weber
  • 690
  • 9
  • 24
Luca B.
  • 638
  • 4
  • 13
  • It only returns `bundle: `. I get how that should affect running the task on boot, but when I start it while the system is running this shouldn't make a difference, right? – Gregor Weber Aug 06 '14 at 12:33
  • Not if upstart runs a new console... try using: `bash -c 'bundle exec rails server'` In your Procfile – Luca B. Aug 06 '14 at 12:36
  • Okay, I have tried it with bash -c. It works fine when I run the Procfile with foreman, but when I start the service I get the following error: "terminated with status 127" which apparently means command not found. – Gregor Weber Aug 06 '14 at 12:55
  • This may be a dumb try but check what you get with just `rails server` and `bash -c 'rails server'` – Luca B. Aug 06 '14 at 12:58
  • Weird, same error as before. Is there some way to get into the same enviroment in which upstart is running those tasks? So I could figure out what is available and what is not? Thanks btw for all your help :) – Gregor Weber Aug 06 '14 at 13:14
  • Upstart should run as if you "sudo su user" from the console. Last try I could suggest you is (IF you're running RVM) placing the rvm source command just after the 'setuid'... OR install ruby from source and go that way (that's cleaner anyway) – Luca B. Aug 06 '14 at 13:25
  • I tried `exec bash -c 'source /usr/local/rvm/scripts/rvm && bundle exec rails server'` but still the errors above :( I'm really confused why that whole thing doesn't work for me – Gregor Weber Aug 06 '14 at 13:43
  • I'm slowly dropping into the "just guess" field but find the bundle path for rvm that should be something on the line of `/home/app/.rvm/gems/ruby-version@global/bin/bundle` and use that ... ALSO, you're running user is 'app' right? ( `setuid app` ) right? – Luca B. Aug 06 '14 at 13:48
  • Weeee got it, you pointed me in the right direction and rvm is able to prepare wrappers to use with something like upstart -> https://rvm.io/integration/init-d Thanks a lot! – Gregor Weber Aug 06 '14 at 13:49
  • Approved your edit obviously! I still suggest, if that will be your production env, to move to either repository ruby (from ruby repos) or from-source compilation – Luca B. Aug 06 '14 at 13:55
  • What is the argument against rvm in production enviroment? I think this provides an easy way to keep up with the most recent ruby version (security fixes wise) – Gregor Weber Aug 09 '14 at 15:02
  • Ruby repos provide a better way to keep your ruby version up to date. In addition you should have no need at all to use rvm (since it's main point is to allow you to use multiple ruby version simultaneously) on your production environment. Plus I honestly had more than a few problems with rvm that more often than not forced me to fully reinstall rvm to get things working again (this opinion is obviously biased). That said my thought is that you **shouldn't** need to use RVM in production – Luca B. Aug 11 '14 at 07:09
1

You can run bundle in another way. Instead of:

web: bundle exec rails server

You need to run:

web: bash -c '~/.rvm/bin/rvm default do bundle exec rails server'

Note: ~/.rvm/bin/rvm - can be replaced with actual path of rvm installation on your server.

Mike P.
  • 35
  • 1
-2

Upstart commands require sudo privileges for the underlying user. Have you considered defining some form of passwordless sudo privileges for your app user to run the rails application service restarts?

e.g In Ubuntu creating a new sudoer definition under /etc/sudoers.d/?

username ALL=(ALL) NOPASSWD:ALL

Once defined 'username' should be able to run the rails app via sudo service 'appname' stop|start|restart.

Here is an explanation for providing the sudo privileges to the user. My Capistrano deployment contains a foreman export definition as below -

namespace :foreman do
 desc 'Export the Procfile to Ubuntu upstart scripts'
 task :export do
   on roles(:app) do |host|
    log_path = shared_path.join('log')
    within release_path do
      execute :mv, ".env .envbkup"
      execute :echo, "'RACK_ENV=#{fetch(:deploy_env)}' >> .env"
      execute :echo, "'RAILS_ENV=#{fetch(:deploy_env)}' >> .env"
      execute :bundle, "exec foreman export upstart #{shared_path}/init -a #{fetch(:application)} -u #{host.user} -l #{log_path}"
      execute :rm, ".env"
      execute :mv, ".envbkup .env"
      as :root do
        execute :cp, "#{shared_path}/init/* /etc/init/"
      end
  end
 end
end

This capistrano definition is invoked from the deploy_env.rb 'after' action.

user553620
  • 775
  • 9
  • 17
  • Noticed my comment was down voted. I am curious to know why. Would appreciate a feedback on why this solution is unacceptable. Thanks. – user553620 Nov 14 '14 at 16:49