Skip to content

Instantly share code, notes, and snippets.

@namelessjon
Created June 8, 2010 18:00
Show Gist options
  • Save namelessjon/430401 to your computer and use it in GitHub Desktop.
Save namelessjon/430401 to your computer and use it in GitHub Desktop.
Simple-ish reloading of the important parts of an app on changes
# Sample configuration file for Unicorn (not Rack)
worker_processes 1
# listen on the sinatra port
listen 4567
# feel free to point this anywhere accessible on the filesystem
pid "#{ENV['XDG_CACHE_HOME']}/unicorn.pid"
stdout_path "#{ENV['XDG_CACHE_HOME']}/unicorn.log"
stderr_path "#{ENV['XDG_CACHE_HOME']}/unicorn.log"
GC.respond_to?(:copy_on_write_friendly=) and
GC.copy_on_write_friendly = true
before_fork do |server, worker|
# this is the important part.
# place all your 'stable' code here, for example rubygems, the ruby stdlib
# maybe even parts of your application. Since it's preloaded, it doesn't
# need to be reloaded when unicorn receives a HUP
require 'sinatra'
require 'haml'
require 'dm-core'
require 'dm-timestamps'
require 'dm-validations'
require 'dm-constraints'
require 'digest/sha1'
require 'redcloth'
require 'mustache'
require 'redis'
require 'yajl'
require 'openssl'
end
#!/usr/bin/ruby
# Jonathan D. Stott <jonathan.stott@gmail.com>
# spawns a unicorn to serve a rack app in the given directory. Watches
# the app files for changes, restarting the unicorn worker when they're
# detected.
#
# A secondary watch passes the unicorn log through to the terminal.
#
# Copyright (c) 2010 Jonathan Stott.
# Released under the terms of the MIT License
require 'directory_watcher'
LOGFILE = "#{ENV['XDG_CACHE_HOME']}/unicorn.log" # unicorn's log file
PIDFILE = "#{ENV['XDG_CACHE_HOME']}/unicorn.pid" # unicorn's pid file
GLOB = ['lib/**/*.rb','app/**/*.rb','app.rb'] # glob of the application's files
# remove the old log
system "rm -f -- #{LOGFILE}"
# start the unicorn
system "unicorn --daemonize --config-file unicorn.config.dev.rb config.ru"
# get the pid
pid = File.open(PIDFILE) { |f| f.read }.chomp.to_i
# open a watcher to read the log as it changes
log_watch = DirectoryWatcher.new File.dirname(LOGFILE),
:glob => File.basename(LOGFILE),
:scanner => :rev,
:pre_load => true
# open the logfile
log = File.open(LOGFILE)
# add an observer to read it
log_watch.add_observer do |*args|
puts log.read
end
# watch our app for changes
dw = DirectoryWatcher.new '.',
:glob => GLOB,
:scanner => :rev,
:pre_load => true
# SIGHUP makes unicorn respawn workers
dw.add_observer do |*args|
Process.kill :HUP, pid
end
# wrap this in a lambda, just to avoid repeating it
stop = lambda { |sig|
Process.kill :QUIT, pid # kill unicorn
dw.stop
log_watch.stop
exit
}
trap("INT", stop)
log_watch.start
dw.start
gets # when the user hits "enter" the script will terminate
stop.call(nil)
@rkh
Copy link

rkh commented Jun 13, 2010

Nice!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment