├── .gitignore ├── .gitmodules ├── Gemfile ├── LICENSE.txt ├── README.md ├── Rakefile ├── lib └── mina │ ├── unicorn.rb │ └── unicorn │ ├── tasks.rb │ ├── utility.rb │ └── version.rb └── mina-unicorn.gemspec /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | *.rbc 3 | .bundle 4 | .config 5 | .yardoc 6 | Gemfile.lock 7 | InstalledFiles 8 | _yardoc 9 | coverage 10 | doc/ 11 | lib/bundler/man 12 | pkg 13 | rdoc 14 | spec/reports 15 | test/tmp 16 | test/version_tmp 17 | tmp 18 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "test/unicorn_test"] 2 | path = test/unicorn_test 3 | url = git@github.com:scarfacedeb/mina-unicorn-test.git 4 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # Specify your gem's dependencies in mina-unicorn.gemspec 4 | gemspec 5 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 tab 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Mina::Unicorn 2 | 3 | [Mina](https://github.com/nadarei/mina) tasks for handle with 4 | [Unicorn](http://unicorn.bogomips.org/) 5 | 6 | This gem provides several mina tasks: 7 | 8 | mina unicorn:start # Start unicorn 9 | mina unicorn:stop # Stop unicorn 10 | mina unicorn:restart # Restart unicorn (with zero-downtime) 11 | 12 | ## Installation 13 | 14 | Add this line to your application's Gemfile: 15 | 16 | gem 'mina-unicorn', :require => false 17 | 18 | And then execute: 19 | 20 | $ bundle 21 | 22 | Or install it yourself as: 23 | 24 | $ gem install mina-unicorn 25 | 26 | ## Usage 27 | 28 | Add this to your `config/deploy.rb` file: 29 | 30 | require 'mina/unicorn' 31 | 32 | Make sure to add the following directories to `:shared_paths` in `config/deploy.rb`: 33 | 34 | ```ruby 35 | set :shared_paths, ['tmp/sockets', 'tmp/pids'] 36 | ``` 37 | 38 | You can also set individual config variables to override default values for 39 | unicorn: 40 | 41 | * `unicorn_env` - set unicorn environment, default: depending on `rails_env`: `development` or `deployment` (see: [Rack environment](http://unicorn.bogomips.org/unicorn_1.html#rack-environment)) 42 | * `rails_env` - set rails environment, default: `production` 43 | * `unicorn_config` - unicorn config file, default: `config/unicorn.rb` 44 | * `unicorn_cmd` - bundle exec unicorn, default: `RAILS_ENV=production bundle exec unicorn` (see: [mina/rails](https://github.com/mina-deploy/mina/blob/master/lib%2Fmina%2Frails.rb#L25)) 45 | * `unicorn_pid` - unicorn pid file, default: `tmp/pids/unicorn.pid` 46 | 47 | Then: 48 | 49 | ``` 50 | $ mina unicorn:start 51 | ``` 52 | 53 | ## Contributing 54 | 55 | 1. Fork it ( http://github.com/scarfacedeb/mina-unicorn/fork ) 56 | 2. Create your feature branch (`git checkout -b my-new-feature`) 57 | 3. Commit your changes (`git commit -am 'Add some feature'`) 58 | 4. Push to the branch (`git push origin my-new-feature`) 59 | 5. Create new Pull Request 60 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require "bundler/gem_tasks" 2 | -------------------------------------------------------------------------------- /lib/mina/unicorn.rb: -------------------------------------------------------------------------------- 1 | load File.expand_path("../unicorn/tasks.rb", __FILE__) 2 | -------------------------------------------------------------------------------- /lib/mina/unicorn/tasks.rb: -------------------------------------------------------------------------------- 1 | require "mina/bundler" 2 | require "mina/deploy" 3 | require "mina/unicorn/utility" 4 | 5 | namespace :unicorn do 6 | include Mina::Unicorn::Utility 7 | 8 | set :unicorn_env, -> { fetch(:rails_env) || fetch(:rack_env) || "deployment" } 9 | set :unicorn_config, -> { "#{fetch(:current_path)}/config/unicorn.rb" } 10 | set :unicorn_pid, -> { "#{fetch(:current_path)}/tmp/pids/unicorn.pid" } 11 | set :unicorn_cmd, -> { "#{fetch(:bundle_prefix, "#{fetch(:bundle_bin)} exec")} unicorn" } 12 | set :unicorn_restart_sleep_time, -> { 2 } 13 | set :bundle_gemfile, -> { "#{fetch(:current_path)}/Gemfile" } 14 | 15 | desc "Start Unicorn master process" 16 | task start: :remote_environment do 17 | command start_unicorn 18 | end 19 | 20 | desc "Stop Unicorn" 21 | task stop: :remote_environment do 22 | command kill_unicorn("QUIT") 23 | end 24 | 25 | desc "Immediately shutdown Unicorn" 26 | task shutdown: :remote_environment do 27 | command kill_unicorn("TERM") 28 | end 29 | 30 | desc "Restart unicorn service" 31 | task restart: :remote_environment do 32 | command restart_unicorn 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /lib/mina/unicorn/utility.rb: -------------------------------------------------------------------------------- 1 | # Ported from: https://github.com/sosedoff/capistrano-unicorn/blob/master/lib/capistrano-unicorn/utility.rb 2 | 3 | module Mina 4 | module Unicorn 5 | module Utility 6 | def start_unicorn 7 | %{ 8 | if [ -e "#{unicorn_pid}" ]; then 9 | if #{unicorn_user} kill -0 `cat #{unicorn_pid}` > /dev/null 2>&1; then 10 | echo "-----> Unicorn is already running!"; 11 | exit 0; 12 | fi; 13 | 14 | #{unicorn_user} rm #{unicorn_pid}; 15 | fi; 16 | 17 | echo "-----> Starting Unicorn..."; 18 | cd #{fetch(:current_path)} && #{unicorn_user} BUNDLE_GEMFILE=#{fetch(:bundle_gemfile)} #{fetch(:unicorn_cmd)} -c #{fetch(:unicorn_config)} -E #{fetch(:unicorn_env)} -D 19 | } 20 | end 21 | 22 | def kill_unicorn(signal) 23 | %{ 24 | if #{unicorn_is_running?}; then 25 | echo "-----> Stopping Unicorn..."; 26 | #{unicorn_send_signal(signal)}; 27 | else 28 | echo "-----> Unicorn is not running."; 29 | fi 30 | } 31 | end 32 | 33 | def restart_unicorn 34 | %{ 35 | #{duplicate_unicorn} 36 | 37 | sleep #{fetch(:unicorn_restart_sleep_time)}; # in order to wait for the (old) pidfile to show up 38 | 39 | if #{old_unicorn_is_running?}; then 40 | #{unicorn_send_signal("QUIT", get_old_unicorn_pid)}; 41 | fi 42 | } 43 | end 44 | 45 | # Send a signal to a unicorn master processes 46 | def unicorn_send_signal(signal, pid=get_unicorn_pid) 47 | "#{unicorn_user} kill -s #{signal} #{pid}" 48 | end 49 | 50 | private 51 | 52 | # Run a command as the :unicorn_user user if :unicorn_user is set 53 | # Otherwise run without sudo 54 | def unicorn_user 55 | "sudo -u #{fetch(:unicorn_user)}" if set?(:unicorn_user) 56 | end 57 | 58 | # Check if a remote process exists using its pid file 59 | # 60 | def remote_process_exists?(pid_file) 61 | "[ -e #{pid_file} ] && #{unicorn_user} kill -0 `cat #{pid_file}` > /dev/null 2>&1" 62 | end 63 | 64 | def duplicate_unicorn 65 | %{ 66 | if #{unicorn_is_running?}; then 67 | echo "-----> Duplicating Unicorn..."; 68 | #{unicorn_send_signal("USR2")}; 69 | else 70 | #{start_unicorn} 71 | fi 72 | } 73 | end 74 | 75 | # Command to check if Unicorn is running 76 | # 77 | def unicorn_is_running? 78 | remote_process_exists?(unicorn_pid) 79 | end 80 | 81 | # Command to check if stale Unicorn is running 82 | # 83 | def old_unicorn_is_running? 84 | remote_process_exists?(old_unicorn_pid) 85 | end 86 | 87 | def unicorn_pid 88 | fetch(:unicorn_pid) 89 | end 90 | 91 | # Stale Unicorn process pid file 92 | def old_unicorn_pid 93 | "#{unicorn_pid}.oldbin" 94 | end 95 | 96 | # Get unicorn master (old) process PID 97 | def get_old_unicorn_pid 98 | get_unicorn_pid(old_unicorn_pid) 99 | end 100 | 101 | # Get unicorn master process PID (using the shell) 102 | def get_unicorn_pid(pid_file=unicorn_pid) 103 | "`cat #{pid_file}`" 104 | end 105 | end 106 | end 107 | end 108 | -------------------------------------------------------------------------------- /lib/mina/unicorn/version.rb: -------------------------------------------------------------------------------- 1 | module Mina 2 | module Unicorn 3 | VERSION = "2.0.0" 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /mina-unicorn.gemspec: -------------------------------------------------------------------------------- 1 | lib = File.expand_path("../lib", __FILE__) 2 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 3 | 4 | require "mina/unicorn/version" 5 | 6 | Gem::Specification.new do |spec| 7 | spec.name = "mina-unicorn" 8 | spec.version = Mina::Unicorn::VERSION 9 | spec.authors = ["tab", "Andrew Volozhanin"] 10 | spec.email = ["scarfacedeb@gmail.com"] 11 | spec.summary = %q{Unicorn tasks for Mina} 12 | spec.description = %q{Unicorn tasks for Mina} 13 | spec.homepage = "https://github.com/scarfacedeb/mina-unicorn" 14 | spec.license = "MIT" 15 | 16 | spec.files = `git ls-files`.split($/) 17 | spec.test_files = [] 18 | spec.require_paths = ["lib"] 19 | 20 | spec.add_dependency "mina", "~> 1.0" 21 | 22 | spec.add_development_dependency "bundler" 23 | spec.add_development_dependency "rake" 24 | end 25 | --------------------------------------------------------------------------------