unicorn working_directory with symlink

deployment, ruby-on-rails-3, signals, unicorn

Solution

The solution was to explicitly set the unicorn binary path, as explained (in somewhat confusing way) on http://unicorn.bogomips.org/Sandbox.html

app_root = "/var/local/project/symlinkfolder"
working_directory app_root
# see http://unicorn.bogomips.org/Sandbox.html
Unicorn::HttpServer::START_CTX[0] = "#{app_root}/vendor/bundle/ruby/1.9.1/bin/unicorn_rails"

Then we needed to issue a `unicorn reload` (`kill -HUP`) command, so unicorn reloads the config file. And from then on, issuing a `USR2` signal works properly.

Problem

We're having trouble hot-deploying with unicorn. We pretty much use the canonical `unicorn.rb` configs, set the `working_directory` to point to the symlink'd folder, but somehow it seems stuck on the actual folder when it was first started and fail to follow the symlink. ``` # config/unicorn.rb if ENV['RAILS_ENV'] == 'production' worker_processes 4 else worker_processes 2 end working_directory "/var/local/project/symlinkfolder" # Listen on unix socket listen "/tmp/unicorn.sock", :backlog => 64 pid "/var/run/unicorn/unicorn.pid" stderr_path "/var/log/unicorn/unicorn.log" stdout_path "/var/log/unicorn/unicorn.log" preload_app true before_fork do |server, worker| # the following is highly recomended for Rails + "preload_app true" # as there's no need for the master process to hold a connection if defined?(ActiveRecord::Base) ActiveRecord::Base.connection.disconnect! end # Before forking, kill the master process that belongs to the .oldbin PID. # This enables 0 downtime deploys. old_pid = "/var/run/unicorn/unicorn.pid.oldbin" if File.exists?(old_pid) && server.pid != old_pid begin Process.kill("QUIT", File.read(old_pid).to_i) rescue Errno::ENOENT, Errno::ESRCH # someone else did our job for us end end end after_fork do |server, worker| # the following is *required* for Rails + "preload_app true", if defined?(ActiveRecord::Base) ActiveRecord::Base.establish_connection end # this makes sure the logging-rails framework works when preload_app = true Logging.reopen # if preload_app is true, then you may also want to check and # restart any other shared sockets/descriptors such as Memcached, # and Redis. TokyoCabinet file handles are safe to reuse # between any number of forked children (assuming your kernel # correctly implements pread()/pwrite() system calls) end ``` When we issue a `USR2`, we see this in the unicorn log: ``` executing ["/var/local/project/project.d/6/vendor/bundle/ruby/1.9.1/bin/unicorn_rails", "-E", "staging", "-D", "-c", "/var/local/project/symlinkfolder/config/unicorn.rb"│· , {12=>#<Kgio::UNIXServer:fd 12>}] (in /var/local/project/project.d/8) ``` so unicorn is somehow 'stuck' on version 6, whilst the actual symlinked folder is on version 8 ... this becomes a problem as soon as we prune folder for version 6 after a few deploys... - The `working_directory` is set to the symlink'd folder - The symlink points to `/var/local/project/project.d/[id]` folder correctly - We update the symlink before sending the `USR2` signal What did we miss??

Original source