I don’t have time to read and I want to jump immediately to the solution →.
Like the 90% of Rails developers, I use Capistrano to manage the deployment of my Rails applications. I also use God to monitor several application processes, such as DelayedJob workers.
The problem
Each time I execute a deployment, I need the restart all the Rails instances, including rake tasks and workers, otherwise they will continue to run with the previous (old) application version.
I cannot simply send a command to God via Capistrano because God is omnipotent and runs with root privileges, while Capistrano doesn’t (for security reasons I don’t deploy with a sudoer user).
Here comes the problem. How to restart God when you deploy a new release? I already discussed this problem in the past and the solution I adopted since today was to execute a command as root without using sudo. The problem with this solution, is that it requires you to type the root password each time you execute a new deploy. And this is extremely awkward.
Last week I was configuring a new Rails application and I decided to investigate a new solution. I really like the way how Phusion Passenger works: whenever you touch the /tmp/restart.txt file, Passenger restarts all the Rails processes.
Why not implementing the same behavior in God? Luckily, someone else already had the same idea before.
The solution
I found the following recipe on Gist.
module God
module Conditions
class RestartFileTouched < PollCondition
attr_accessor :restart_file
def initialize
super
end
def process_start_time
Time.parse(`ps -o lstart -p #{self.watch.pid} --no-heading`)
end
def restart_file_modification_time
File.mtime(self.restart_file)
end
def valid?
valid = true
valid &= complain("Attribute 'restart_file' must be specified", self) if self.restart_file.nil?
valid
end
def test
process_start_time < restart_file_modification_time
end
end
end
end
Save the code in your God application or on the server and make sure God loads it. My suggestion is to add the following line in the God configuration script (e.g. /etc/god/config)
# Load in all God shared configs. # Share configs apply to all instances. God.load "/etc/god/conf.d/*.god"
and save the file in the /etc/god/conf.d folder. In this way, when you’ll start God with
$ god -c /etc/god/config
all the shared recipes will be loaded.
Then, configure the monitored process to watch the restart file. The configuration is available as a state transition condition.
rails_root = "/path/to/rails" restart.condition(:restart_file_touched) do |c| c.interval = 5.seconds c.restart_file = File.join(rails_root, 'tmp', 'restart.txt') end
Taking the GitHub DelayedJob recipe as example, you should change
# restart if memory gets too high
w.transition(:up, :restart) do |on|
on.condition(:memory_usage) do |c|
c.above = 300.megabytes
c.times = 2
end
end
to
# restart if memory gets too high
w.transition(:up, :restart) do |on|
on.condition(:memory_usage) do |c|
c.above = 300.megabytes
c.times = 2
end
on.condition(:restart_file_touched) do |c|
c.interval = 5.seconds
c.restart_file = File.join(rails_root, 'tmp', 'restart.txt')
end
end
The restart_file can be whichever file you want. I strongly encourage to use the same /tmp/restart.txt Passenger file, in this way your processes will restart each time you restart the application.
Thanks to Amedeo for his help and thanks to Nathan Humbert for creating the original God configuration.


On which OS have you tested this? With me: on OSX it will error out constantly and on debian it constantly restarts.
I tested it with Ubuntu and OpenSUSE, and it works in both cases.
D [2011-02-09 11:30:03] DEBUG: xxx-dj-1 RestartFileTouched [false] {true=>:restart} D [2011-02-09 11:30:03] DEBUG: driver schedule # in 5 seconds
I [2011-02-09 11:30:06] INFO: xxx-dj-0 [ok] (RestartFileTouched)
D [2011-02-09 11:30:06] DEBUG: xxx-dj-0 RestartFileTouched [false] {true=>:restart}
D [2011-02-09 11:30:06] DEBUG: driver schedule # in 5 seconds
I [2011-02-09 11:30:07] INFO: xxx-emails-0 [ok] (RestartFileTouched)
D [2011-02-09 11:30:07] DEBUG: xxx-emails-0 RestartFileTouched [false] {true=>:restart}
D [2011-02-09 11:30:07] DEBUG: driver schedule # in 5 seconds
I [2011-02-09 11:30:08] INFO: xxx-dj-1 [trigger] (RestartFileTouched)
D [2011-02-09 11:30:08] DEBUG: xxx-dj-1 RestartFileTouched [true] {true=>:restart}
I [2011-02-09 11:30:08] INFO: xxx-dj-1 move 'up' to 'restart'
I [2011-02-09 11:30:08] INFO: xxx-dj-1 stop: default lambda killer
I [2011-02-09 11:30:08] INFO: xxx-dj-1 sent SIGTERM
I [2011-02-09 11:30:10] INFO: xxx-dj-1 process stopped
I [2011-02-09 11:30:10] INFO: xxx-dj-1 start: rake -f /var/www/apps/xxx/current/Rakefile jobs:work RAILS_ENV=production
Wait, I’m probably wrong: “INFO: unicorn [ok] (RestartFileTouched)” means that it’s doesn’t need to restart. Double negations…
You also could just add a single command to execute with root rights within the /etc/sudoers file like this:
your_normal_user ALL = (root) /usr/sbin/apache2ctl, /etc/init.d/memcached, /usr/bin/gem, /etc/init.d/god, /usr/bin/god
as I currently configured my server… spare you a lot of hassle
I don’t want the deployment user to have root privileges for security reason.
Tried this and had many problems with it, especially because the format of “ps” arguments didn’t work for FreeBSD. Also, I think it’s not the cleanest way to do this. I prefer using sudo to allow the deploying user to “god restart”. Then all you need to do is adding
namespace :deploy do
task :start do ; end
task :stop do ; end
task :restart, :roles => :app, :except => { :no_release => true } do
sudo “god restart YOUR-PROJECT”
end
end
to config/deploy.rb
/usr/local/etc/sudoers:
…
deployinguser ALL=(root) NOPASSWD: /usr/local/bin/god restart THEPROJECT
For FreeBSD, change to:
Time.parse(`ps -o lstart=”" -p #{self.watch.pid}`)
May work on other platforms too, but untested. Hint was found at: http://code.google.com/p/xinc/issues/detail?id=185
Summary of my approach: http://blog.dev001.net/post/12532098051/how-to-restart-god-after-deploying-a-rails-app-with
Awesome! Thank you for this. I knew about the sudo privilege thing, but this is way cleaner since I will be deploying multiple apps for different developers I’m working with onto the same server. I really like this technique and it gives me one less thing to configure every time I create a new application. Thanks!
Actually, that is not working for me at all. I discovered this is because I am using it for unicorn restarts. Unicorn doesn’t actually quit and start again, so the ps lstart timestamp doesn’t change. (You just send it a HUP signal and it restarts itself.)
But check this out: https://github.com/cyrilpic/god/blob/0862ec8d889470b8de09e6b75e50de2c306951d0/lib/god/conditions/file_touched.rb
It’s an open pull request right now, but just wget and “sudo god load” that rb file, and you are good to go!
If you want to take advantage of events, you’re gonna need to use sudo.
I did a yet another take on this, running god as a non-root user, together with Bundler. Also tried to make sure that the workers restart gracefully.
http://blog.flowdock.com/2012/08/29/capistrano-god-bundler-resque-configuration/
Nicely done :)
For me it stops working after the first touch of the restart file.
God does not perform the RestartFileTouched condition test anymore..
Any suggestions?