7

I'm trying to setup a Resque worker as an Upstart init script to be used by Monit in a Rails app. I'm not a sysop and I've tried to write this using examples from other init script we have on our server, here's what I got:

start on startup
stop on shutdown

pre-start script
   cd /var/www/my-app/current
end script

script
   exec bundle exec rake environment resque:work RAILS_ENV=staging PIDFILE=/var/run/resque.pid QUEUE=sync >> /var/log/resque.log
end script

But it doesn't work, if I try sudo start resque I get:

resque start/running, process XXXX

Nothing is being started as far as I know, there's no Resque process to be found nor there's log file. I'm quite lost as to how to get it working.

Update: I've found the syslog file and it says:

Nov  4 17:20:09 fantasysports init: resque main process (3057) terminated with status 2

Update: I've tried to run it using sudo (yeah that doesn't make sense!) and removed the output redirection to the log file and now I get a different status code:

Nov  4 17:29:44 fantasysports init: resque main process (3276) terminated with status 10

Update: Ended up ditching Upstart for init.d, as start-stop-daemon is much better documented and it give me complete control of what's going on.

Nicolas Buduroi
  • 275
  • 3
  • 10

3 Answers3

5

Here's how I do it.. this also adds in rvm

start on startup
stop on starting rcS

chdir /data/pusher/current
env RAILS_ENV=production
script
  /usr/local/bin/rvm-shell '1.9.2@app' -c 'JOBS_PER_FORK=25 RAILS_ENV=production QUEUE=app_production bundle exec rake --trace resque:work >> /data/app/current/log/app-worker.production.log 2>&1'
end script

Edit: here is how I do it for running as a different user.. chdir doesn't seem to be honored.. so it's kind of hacky

start on runlevel [2345]
stop on starting rcS

chdir /data/app/current
env RAILS_ENV=production
script
        sudo -u user -s -- "cd /data/app/current; export RAILS_ENV=production; /usr/local/bin/rvm-shell '1.9.2-p180@app' -c 'QUEUE=app_production bundle exec rake resque:work >> /data/app/current/log/app-worker.production.log 2>&1'"
end script

You pretty much need to change into the correct directory and set the RAILS_ENV in the sudo command

Mike
  • 21,910
  • 7
  • 55
  • 79
  • Thanks a lot, it was the cd command that was causing the problem! Didn't knew about chdir. – Nicolas Buduroi Nov 04 '11 at 21:41
  • Do you have any idea how to change the owner of the process? – Nicolas Buduroi Nov 05 '11 at 17:02
  • edited my post.. there might be a better way to do this... but this works – Mike Nov 05 '11 at 18:15
  • I found another trick for switching user which might be neater - pipe it into sudo bash. `exec echo 'cd /home/user ; RAILS_ENV=production bundle exec ....' | sudo -u user -i bash` – mahemoff Jan 21 '12 at 13:28
  • 1
    Just like chdir DIR works to change directory there is also: setuid and setgid. See http://upstart.ubuntu.com/cookbook/#setgid – Dima Feb 08 '13 at 20:15
2

You might want to look at Foreman: http://ddollar.github.com/foreman/ which has the ability to export to upstart and is recommended for managing resque workers in a number of posts, including this one: http://michaelvanrooijen.com/articles/2011/06/08-managing-and-monitoring-your-ruby-application-with-foreman-and-upstart/

xentek
  • 351
  • 1
  • 2
  • 7
1

The way that the RVM manual, in the "integration" section, recommends for "Using RVM and Ruby-based services that start via init.d or upstart" is to use RVM aliases and wrappers.

I had a situation where I had to monitor a bluepill process. This process is a daemon so a process that forks 2 times. Starting it with the rvm-shell command added a third fork... Which caused Upstart to not be able to track the process PID (it can track processes max only till the second fork - when given the expect daemon stanza).

I solved this in the following way:

  1. First I created an RVM alias for my environment:

    rvm alias create my_app ruby-2.0.0-p247@my_app

  2. Then I have used the following upstart config for my job:

` # /etc/init/bluepill_my-app.conf

description "my_app Bluepill"

start on runlevel [2]
stop on runlevel [016]

setuid my-app
setgid my-app

expect daemon
respawn

env USER=my-app
env HOME=/var/www/my-app/
env RAILS_ENV=my-app
env BLUEPILL_BASE_DIR=/tmp/bluepill_my-app

chdir /var/www/my-app/current/

exec /var/www/my-app/.rvm/wrappers/my-app/bundle exec bluepill --no-privileged load  /var/www/my-app/current/config/deploy/monitoring/my-app.pill >> /tmp/upstart.log 2>&1

`

Bundler needs to be installed in the given gemset to which the RVM alias is pointing to.

Calling the bundler wrapper script does not cause any forks like the rvm-shell command does.

An alternative could be to install the bluepill gem in the used gemset, create a wrapper script for it and use it directly without the bundle exec - just like the RVM manual suggests - but using it via bunlder allows the bluepill .pill files to use any library ussed in my-app (like setingslogic etc.).

This got a little bit off topic, but I think it's a good example how to do it better. I hope this helps.

Szymon Jeż
  • 3,267
  • 3
  • 16
  • 17
  • 1
    Thank you very much Simon You've solved the problem I've been trying to solve for 5 hours. I have to install the bundler gem in the gemset in order to be able to run bundle exec in upstart using the gemset. The system was using bundler from the default gemset and It wasn't be able to access the gems I had installed with bundle install. –  Oct 30 '14 at 11:00