Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Starting background tasks with Capistrano

For my RubyOnRails-App I have to start a background job at the end of Capistrano deployment. For this, I tried the following in deploy.rb:

run "nohup #{current_path}/script/runner -e production 'Scheduler.start' &", :pty => true

Sometimes this works, but most of the time it does not start the process (= not listed in ps -aux). And there are no error messages. And there is no nohup.out, not in the home directory and not in the rails app directory.

I tried using trap('SIGHUP', 'IGNORE') in scheduler.rb instead of nohup, but the result is the same.

The only way to get it work is removing the ":pty => true" and do a manual Ctrl-C at the end of "cap deploy". But I don't like this...

Are there any other chances to invoke this Scheduler.start? Or to get some more error messages?

I'm using Rails 2.3.2, Capistrano 2.5.8, Ubuntu Hardy on the Server

like image 424
Georg Ledermann Avatar asked Jul 10 '09 12:07

Georg Ledermann


3 Answers

With :pty => true, user shell start-up scripts (e.g. bashrc, etc.) are (usually) not loaded. My ruby program exited right after launching because of the lack of dependent environment variables.

Without :pty => true, as you described in the question, capistrano hangs there waiting for the process to exit. You'll need to redirect both stdout and stderr to make it return immediately.

run 'nohup ruby -e "sleep 5" &' # hangs for 5 seconds
run 'nohup ruby -e "sleep 5" > /dev/null &' # hangs for 5 seconds
run 'nohup ruby -e "sleep 5" > /dev/null 2>&1 &' # returns immediately. good.

If your background task still doesn't run. Try redirecting stdout and stderr to a log file so that you can investigate the output.

like image 70
Arrix Avatar answered Nov 01 '22 18:11

Arrix


I'd like to share my solution which also works when executing multiple commands. I tried many other variants found online, including the "sleep N" hack.

run("nohup sh -c 'cd #{release_path} && bundle exec rake task_namespace:task_name RAILS_ENV=production > ~/shared/log/<rakelog>.log &' > /dev/null 2>&1", :pty => true)

This is a dup response launching background process in capistrano task but want to make sure others and myself can google for this solution.

like image 31
okor Avatar answered Nov 01 '22 19:11

okor


Do you want your Scheduler job to run continually in the background and get restarted when you run Capistrano?

If so, then for that I use runit http://smarden.sunsite.dk/runit/ and DelayedJob http://github.com/Shopify/delayed_job/tree/master

  1. Install runit in the mode of not replacing init
  2. Add your background job as a runit service and add the log monitor for it from runit.
  3. Have Capistrano call sudo sv kill job_name to kill and restart the job.

My backround job is an instance of the Rails plugin DelayedJob which handles background Rails tasks. I kill it with every Capistrano deploy so it will restart with the updated code base.

This has proved to be very reliable.

HTH,

Larry

like image 1
Larry K Avatar answered Nov 01 '22 18:11

Larry K