How to restart Rails from within Rails?
Asked Answered
C

3

7

Ok, so I would like to create an action in Rails to restart itself. I did a little searching and found:

http://snippets.dzone.com/posts/show/5002

Which suggests 2 commands, one to stop and another to restart. The following kills:

ps -a|grep "/usr/local/bin/ruby script/server"|grep -v "grep /usr"|cut -d " " -f1|xargs -n 1 kill -KILL $1

The -HUP signal doesn't restart for me, so I tried to mangle the above command (adjusted so the command worked fine with how I was starting the server under Ubuntu):

ps -eaf|grep "ruby script/server"|grep -v grep|cut -d " " -f3|xargs -n 1 kill -KILL $1;script/server

This works fine in my environment, so I tried to set up an action to execute it:

def restart
  fork { exec "ps -eaf|grep \"ruby script/server\"|grep -v grep|cut -d \" \" -f3|xargs -n 1 kill -KILL $1;script/server" }
  redirect_to "/server_maintenance"
end

The action kills the server fine, but doesn't actually start the server back up:

=> Booting Mongrel
=> Rails 2.3.2 application starting on http://0.0.0.0:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server
Exiting
/usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel/tcphack.rb:12:in `initialize_without_backlog': Address already in use - bind(2) (Errno::EADDRINUSE)
    from /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel/tcphack.rb:12:in `initialize'
    from /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:93:in `new'
    from /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:93:in `initialize'
    from /usr/lib/ruby/gems/1.8/gems/actionpack-2.3.2/lib/action_controller/vendor/rack-1.0/rack/handler/mongrel.rb:10:in `new'
    from /usr/lib/ruby/gems/1.8/gems/actionpack-2.3.2/lib/action_controller/vendor/rack-1.0/rack/handler/mongrel.rb:10:in `run'
    from /usr/lib/ruby/gems/1.8/gems/rails-2.3.2/lib/commands/server.rb:111
    from /usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require'
    from /usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:31:in `require'
    from script/server:3

I'm not quite understanding why the address is already in use when Mongrel seems to have just exited.

I found this question:

How do you restart Rails under Mongrel, without stopping and starting Mongrel

but the signals don't cause the restart in my environment, they just end up killing the process.

Anyone have any ideas on what may work? For some notes on my environment: I installed Rails from a new version of RubyGems, and Mongrel. I use script/server to start the server, which of course uses Mongrel. I'm on Ubuntu Hardy Heron.

Clupeid answered 7/4, 2009 at 6:30 Comment(0)
C
3

Ok I found a fix... I changed how I start rails to:

mongrel_rails start -d

and now the following action will do it:

def restart
  fork { exec "mongrel_rails restart" }
  redirect_to "/server_maintenance"
end

As a caveat, the redirect_to will cause a failed load because the server will be down... however a reload after a pause will show that the restart was successful. This could be fixed by changing the restart to be done with AJAX, followed by a javascript reload... but I will leave that as an exercise to the reader.

Clupeid answered 7/4, 2009 at 7:7 Comment(0)
I
4

If you don't mind switching to mod_rails, you can restart your server by creating $RAILS_ROOT/tmp/restart.txt, which causes only the Rails instance you care about to restart.

Your PS command looks (cursorary glance) like it will kill all rails processes on your box. That's fine if you are the only Rails app on a machine, but if there's a few running as the same user or you are running as root you'll kill them all. Bad form!

This points it out for mongrel. There's the way you want to try.

Intracranial answered 7/4, 2009 at 7:5 Comment(1)
Thanks for the response! I actually got it working a bit before you responded, but the link pretty much shows how I got it working, so will upvote!Clupeid
C
3

Ok I found a fix... I changed how I start rails to:

mongrel_rails start -d

and now the following action will do it:

def restart
  fork { exec "mongrel_rails restart" }
  redirect_to "/server_maintenance"
end

As a caveat, the redirect_to will cause a failed load because the server will be down... however a reload after a pause will show that the restart was successful. This could be fixed by changing the restart to be done with AJAX, followed by a javascript reload... but I will leave that as an exercise to the reader.

Clupeid answered 7/4, 2009 at 7:7 Comment(0)
T
0

In our consulting with startups running their sites on Rails, we used two methods for managing mongrel processes.

First, is a custom gem we wrote called mongrel_runit. This sets mongrels up as services in runit.

Second, we used god to monitor mongrel processes. This will work with mongrel_runit, or with 'normal' mongrel configurations.

Titbit answered 7/4, 2009 at 13:54 Comment(1)
Thanks for the response! Unfortunately, this doesn't exactly meet my personal needs. Also I would suggest you add some more information about mongrel_runit both here and on the project page... it's not entirely clear what it does.Clupeid

© 2022 - 2024 — McMap. All rights reserved.