How to start a rake task using upstart
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.
Solution 1:
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
Solution 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/
Solution 3:
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:
-
First I created an RVM alias for my environment:
rvm alias create my_app ruby-2.0.0-p247@my_app
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.