<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>lanvige (Lanvige Jiang)</title>
    <link>https://ruby-china.org/lanvige</link>
    <description>Coder</description>
    <language>en-us</language>
    <item>
      <title>Rails Variants Tips</title>
      <description>&lt;p&gt;原贴 &lt;a href="http://lanvige.github.io/2014/09/11/rails-variants-tips/" rel="nofollow" target="_blank" title=""&gt;http://lanvige.github.io/2014/09/11/rails-variants-tips/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;现在 Web 界流行一个新词&lt;a href="http://en.wikipedia.org/wiki/Responsive_web_design" rel="nofollow" target="_blank" title=""&gt;Responsive Web Design&lt;/a&gt;，目的就是让一套网页在不同的设备上都能展现内容，像 BootStrap 这样的主流框架也都对其进行支持，很是方便，但有时不同设备上要求是不同的，可以说是完全不同的样式，在开发过程中仍需要使用不同的模板来渲染。&lt;/p&gt;

&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/2014/fd7b63df56678774484db504b797ccf1.jpg" title="" alt=""&gt;
&lt;a href="http://codemy.net/posts/rails-4-1-variants" rel="nofollow" target="_blank" title=""&gt;Image source:&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;提到不同模板，在 Rails 中，普遍的方案是加入一个新的 Mime，为这种 Mime 建一个 Template Engine。 
示例：&lt;a href="http://railscasts.com/episodes/199-mobile-devices" rel="nofollow" target="_blank" title=""&gt;RailsCasts #199 Mobile Devices&lt;/a&gt;。&lt;/p&gt;
&lt;h3 id="Action Pack Variants"&gt;Action Pack Variants&lt;/h3&gt;
&lt;p&gt;Rails 4.1 中推出了一个新功能 &lt;a href="http://guides.rubyonrails.org/4_1_release_notes.html#action-pack-variants" rel="nofollow" target="_blank" title=""&gt;Action Pack Variants&lt;/a&gt;，主要就是简化多设备上的模板问题。&lt;/p&gt;
&lt;h3 id="具体用法"&gt;具体用法&lt;/h3&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;#抄自 release notes&lt;/span&gt;

&lt;span class="c1"&gt;# You can set the variant in a before_action:&lt;/span&gt;
&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;variant&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:tablet&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;user_agent&lt;/span&gt; &lt;span class="o"&gt;=~&lt;/span&gt; &lt;span class="sr"&gt;/iPad/&lt;/span&gt;

&lt;span class="c1"&gt;#Respond to variants in the action just like you respond to formats:&lt;/span&gt;
&lt;span class="n"&gt;respond_to&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;html&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tablet&lt;/span&gt; &lt;span class="c1"&gt;# renders app/views/projects/show.html+tablet.erb&lt;/span&gt;
    &lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;phone&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;extra_setup&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# Provide separate templates for each format and variant:&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;views&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;projects&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;show&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;html&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;erb&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;views&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;projects&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;show&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;html&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;tablet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;erb&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;views&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;projects&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;show&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;html&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;phone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;erb&lt;/span&gt;
&lt;span class="no"&gt;You&lt;/span&gt; &lt;span class="n"&gt;can&lt;/span&gt; &lt;span class="n"&gt;also&lt;/span&gt; &lt;span class="n"&gt;simplify&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;variants&lt;/span&gt; &lt;span class="n"&gt;definition&lt;/span&gt; &lt;span class="n"&gt;using&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;inline&lt;/span&gt; &lt;span class="ss"&gt;syntax:

&lt;/span&gt;&lt;span class="n"&gt;respond_to&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;js&lt;/span&gt;         &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="s2"&gt;"trash"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;html&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;phone&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="n"&gt;progress_path&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;html&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;none&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="s2"&gt;"trash"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="Tip 1 判断浏览器类型"&gt;Tip 1 判断浏览器类型&lt;/h3&gt;
&lt;p&gt;判断浏览器是一件很烦的事情，好在有很多地方都已经写好可以借用：如&lt;a href="https://github.com/ruby-china/ruby-china/blob/master/app/helpers/application_helper.rb#L97" rel="nofollow" target="_blank" title=""&gt;ruby-china&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;不过这里要推荐的是一个 gem，叫作&lt;a href="https://github.com/fnando/browser" rel="nofollow" target="_blank" title=""&gt;browser&lt;/a&gt;&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;'browser'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后就可以享受到多如牛毛的判断，更多看 github 页面。&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt; 
&lt;span class="n"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mobile?&lt;/span&gt;
&lt;span class="n"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tablet?&lt;/span&gt;
&lt;span class="n"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;firefox?&lt;/span&gt;
&lt;span class="n"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ie?&lt;/span&gt;
&lt;span class="n"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ie6?&lt;/span&gt;      
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="Tip 2 参数指定浏览器类型"&gt;Tip 2 参数指定浏览器类型&lt;/h3&gt;
&lt;p&gt;通过手机，模拟器可以看到效果，但调试起来却不方便，在 Chrome 中安装 Agnet Simulate 是个好办法，但... RailsCast 中给出了一个通过 params 来改变状态的方法，这里依然实用。&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;mobile_device?&lt;/span&gt;
  &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:mobile_override&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:mobile&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:mobile&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:mobile_override&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:mobile_override&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'1'&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="n"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mobile?&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;通过 params &lt;code&gt;mobile=1&lt;/code&gt; 来强制设定浏览器类型，然后将其存到 session 中，即可以方便的调试。&lt;/p&gt;
&lt;h3 id="Tip 3 Devise等如何使用"&gt;Tip 3 Devise 等如何使用&lt;/h3&gt;
&lt;p&gt;上面示例中，把判断设备的代码放在了 &lt;code&gt;application_controller.rb&lt;/code&gt; 中，但如果在像 devise 中如何使用 Variants 呢？&lt;/p&gt;

&lt;p&gt;因为 devise 的自定义类中，会继承&lt;code&gt;class RegistrationsController &amp;lt; ::Devise::RegistrationsController&lt;/code&gt;，而非 &lt;code&gt;application_controller.rb&lt;/code&gt;，所以判断方法无法在这里使用。&lt;/p&gt;

&lt;p&gt;第一个方案是，在自定义类中重写一变判断方法，Too Sha too kill...&lt;/p&gt;

&lt;p&gt;第二种，可以使用&lt;code&gt;Concerns&lt;/code&gt;&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# controllers/concerns/detect_format_variant.rb&lt;/span&gt;
&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;DetectFormatVariant&lt;/span&gt;
  &lt;span class="kp"&gt;extend&lt;/span&gt; &lt;span class="no"&gt;ActiveSupport&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Concern&lt;/span&gt;

  &lt;span class="n"&gt;included&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;before_filter&lt;/span&gt; &lt;span class="ss"&gt;:set_device_type&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="kp"&gt;private&lt;/span&gt;

  &lt;span class="c1"&gt;## Mobile device&lt;/span&gt;
  &lt;span class="c1"&gt;# detect_device&lt;/span&gt;
  &lt;span class="c1"&gt;# 用Rails 4.1中的variants来进行设备匹配&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;set_device_type&lt;/span&gt;
    &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:mobile_override&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:mobile&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:mobile&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;mobile_device?&lt;/span&gt;
      &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;variant&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:phone&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;mobile_device?&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:mobile_override&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:mobile_override&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'1'&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="n"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mobile?&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在需要进行判断的 controller 中加入&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Base controller
class ApplicationController &amp;lt; ActionController::Base
  include DetectFormatVariant
end

# Devise
class RegistrationsController &amp;lt; ::Devise::RegistrationsController
  include DetectFormatVariant
end
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="REF::"&gt;REF::&lt;/h2&gt;
&lt;p&gt;如果想深入了解 Variants，可以看看这篇：
&lt;a href="http://ryanbigg.com/2009/04/how-rails-works-2-mime-types-respond_to/" rel="nofollow" target="_blank"&gt;http://ryanbigg.com/2009/04/how-rails-works-2-mime-types-respond_to/&lt;/a&gt;&lt;/p&gt;</description>
      <author>lanvige</author>
      <pubDate>Thu, 11 Sep 2014 20:04:13 +0800</pubDate>
      <link>https://ruby-china.org/topics/21489</link>
      <guid>https://ruby-china.org/topics/21489</guid>
    </item>
    <item>
      <title>Sidekiq 精通 36 分钟</title>
      <description>&lt;p&gt;原贴 &lt;a href="http://lanvige.github.io/2014/06/10/sidekiq-in-rails/" rel="nofollow" target="_blank" title=""&gt;http://lanvige.github.io/2014/06/10/sidekiq-in-rails/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/2014/f6fe2633d1118a8d6fd59c645f937022.jpg" title="" alt=""&gt;&lt;br&gt;
Image modify from &lt;a href="http://blog.whitepages.com/wp-content/uploads/2012/12/steps3-41.jpg" rel="nofollow" target="_blank" title=""&gt;whitepages&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://sidekiq.org/" rel="nofollow" target="_blank"&gt;http://sidekiq.org/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/mperham/sidekiq" rel="nofollow" target="_blank"&gt;https://github.com/mperham/sidekiq&lt;/a&gt;&lt;br&gt;
&lt;a href="http://railscasts.com/episodes/366-sidekiq" rel="nofollow" target="_blank"&gt;http://railscasts.com/episodes/366-sidekiq&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;阅读前需要了解 Redis、Background Job 等概念，本文自动化部署使用的是 Capistrano 3。&lt;/p&gt;
&lt;h2 id="Rails中配置Sidekiq"&gt;Rails 中配置 Sidekiq&lt;/h2&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;gem &lt;span class="nb"&gt;install &lt;/span&gt;sidekiq

&lt;span class="c"&gt;# Installing connection_pool 2.0.0&lt;/span&gt;
&lt;span class="c"&gt;# Installing redis 3.0.7&lt;/span&gt;
&lt;span class="c"&gt;# Installing redis-namespace 1.4.1&lt;/span&gt;
&lt;span class="c"&gt;# Installing sidekiq 3.1.3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;将 Redis 的配置信息放到 Rails 4 中的&lt;code&gt;secrets.yml&lt;/code&gt;中：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="ss"&gt;redis: &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;redis&lt;/span&gt;
   &lt;span class="ss"&gt;redis_server: &lt;/span&gt;&lt;span class="s1"&gt;'localhost'&lt;/span&gt;
   &lt;span class="ss"&gt;redis_port: &lt;/span&gt;&lt;span class="mi"&gt;6379&lt;/span&gt;
   &lt;span class="ss"&gt;redis_db_num: &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
   &lt;span class="ss"&gt;redis_namespace: &lt;/span&gt;&lt;span class="s1"&gt;'highlander_sidekiq'&lt;/span&gt;


&lt;span class="ss"&gt;development:
  &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;redis&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在&lt;code&gt;initializers&lt;/code&gt;下新建&lt;code&gt;sidekiq.rb&lt;/code&gt;文件，用来初始化 Redis 和 Sidekiq config&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;redis_server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;secrets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;redis_server&lt;/span&gt;
&lt;span class="n"&gt;redis_port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;secrets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;redis_port&lt;/span&gt;
&lt;span class="n"&gt;redis_db_num&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;secrets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;redis_db_num&lt;/span&gt;
&lt;span class="n"&gt;redis_namespace&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;secrets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;redis_namespace&lt;/span&gt;


&lt;span class="no"&gt;Sidekiq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;configure_server&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="n"&gt;redis_server&lt;/span&gt;
  &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;redis&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;url: &lt;/span&gt;&lt;span class="s2"&gt;"redis://&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;redis_server&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;redis_port&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;redis_db_num&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;namespace: &lt;/span&gt;&lt;span class="n"&gt;redis_namespace&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="no"&gt;Sidekiq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;configure_client&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;redis&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;url: &lt;/span&gt;&lt;span class="s2"&gt;"redis://&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;redis_server&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;redis_port&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;redis_db_num&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;namespace: &lt;/span&gt;&lt;span class="n"&gt;redis_namespace&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="sidekiq 配置参数"&gt;sidekiq 配置参数&lt;/h4&gt;
&lt;p&gt;命令后加上 &lt;code&gt;--help&lt;/code&gt; 可以看到其配置参数：&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;bundle &lt;span class="nb"&gt;exec &lt;/span&gt;sidekiq &lt;span class="nt"&gt;--help&lt;/span&gt;
    &lt;span class="nt"&gt;-c&lt;/span&gt;, &lt;span class="nt"&gt;--concurrency&lt;/span&gt; INT            processor threads to use
    &lt;span class="nt"&gt;-d&lt;/span&gt;, &lt;span class="nt"&gt;--daemon&lt;/span&gt;                     Daemonize process
    &lt;span class="nt"&gt;-e&lt;/span&gt;, &lt;span class="nt"&gt;--environment&lt;/span&gt; ENV            Application environment
    &lt;span class="nt"&gt;-g&lt;/span&gt;, &lt;span class="nt"&gt;--tag&lt;/span&gt; TAG                    Process tag &lt;span class="k"&gt;for &lt;/span&gt;procline
    &lt;span class="nt"&gt;-i&lt;/span&gt;, &lt;span class="nt"&gt;--index&lt;/span&gt; INT                  unique process index on this machine
    &lt;span class="nt"&gt;-q&lt;/span&gt;, &lt;span class="nt"&gt;--queue&lt;/span&gt; QUEUE[,WEIGHT]       Queues to process with optional weights
    &lt;span class="nt"&gt;-r&lt;/span&gt;, &lt;span class="nt"&gt;--require&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;PATH|DIR]         Location of Rails application with workers or file to require
    &lt;span class="nt"&gt;-t&lt;/span&gt;, &lt;span class="nt"&gt;--timeout&lt;/span&gt; NUM                Shutdown &lt;span class="nb"&gt;timeout&lt;/span&gt;
    &lt;span class="nt"&gt;-v&lt;/span&gt;, &lt;span class="nt"&gt;--verbose&lt;/span&gt;                    Print more verbose output
    &lt;span class="nt"&gt;-C&lt;/span&gt;, &lt;span class="nt"&gt;--config&lt;/span&gt; PATH                path to YAML config file
    &lt;span class="nt"&gt;-L&lt;/span&gt;, &lt;span class="nt"&gt;--logfile&lt;/span&gt; PATH               path to writable logfile
    &lt;span class="nt"&gt;-P&lt;/span&gt;, &lt;span class="nt"&gt;--pidfile&lt;/span&gt; PATH               path to pidfile
    &lt;span class="nt"&gt;-V&lt;/span&gt;, &lt;span class="nt"&gt;--version&lt;/span&gt;                    Print version and &lt;span class="nb"&gt;exit&lt;/span&gt;
    &lt;span class="nt"&gt;-h&lt;/span&gt;, &lt;span class="nt"&gt;--help&lt;/span&gt;                       Show &lt;span class="nb"&gt;help&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/mperham/sidekiq/wiki/Advanced-Options#queues" rel="nofollow" target="_blank" title=""&gt;Queues 的用法&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;可以通过 linux cli 的方式，使用添数来启动 sidekiq: &lt;code&gt;bundle exec sidekiq -q queue_name_1,queue_name_2&lt;/code&gt;，也可以将这些参数放到 yml 中，通过 -C 参数来启动 &lt;code&gt;bundle exec sidekiq -C config/sidekiq.yml&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;sidekiq 启动配置文件&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="ss"&gt;:concurrency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="ss"&gt;:pidfile&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;pids&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;sidekiq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pid&lt;/span&gt;

&lt;span class="ss"&gt;:queues&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;
    &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;myqueue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="ss"&gt;development:
  :concurrency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="ss"&gt;staging:
  :concurrency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;span class="ss"&gt;production:
  :concurrency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="Worker"&gt;Worker&lt;/h2&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SmsWorker&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Sidekiq&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Worker&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;perform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# do something&lt;/span&gt;
    &lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="nb"&gt;name&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="Run"&gt;Run&lt;/h2&gt;
&lt;p&gt;配置好这些东西，就可以对刚才写的 SmsWorker 进行测试了。&lt;/p&gt;

&lt;p&gt;首先，要启动 Sidekiq:&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;bundle &lt;span class="nb"&gt;exec &lt;/span&gt;sidekiq &lt;span class="nt"&gt;-C&lt;/span&gt; config/sidekiq.yml                                                   ✘

&lt;span class="s2"&gt;"localhost"&lt;/span&gt;
2014-06-10T05:08:07Z 36163 TID-ox8pyjylc INFO: Booting Sidekiq 3.1.3 with redis options &lt;span class="o"&gt;{&lt;/span&gt;:url&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="s2"&gt;"redis://localhost:6379/0"&lt;/span&gt;, :namespace&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="s2"&gt;"highlander_sidekiq"&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;

         s
        ss
   sss  sss         ss
   s  sss s   ssss sss   ____  _     _      _    _
   s     sssss ssss     / ___|&lt;span class="o"&gt;(&lt;/span&gt;_&lt;span class="o"&gt;)&lt;/span&gt; __| | ___| | _&lt;span class="o"&gt;(&lt;/span&gt;_&lt;span class="o"&gt;)&lt;/span&gt; __ _
  s         sss         &lt;span class="se"&gt;\_&lt;/span&gt;__ &lt;span class="se"&gt;\|&lt;/span&gt; |/ _&lt;span class="sb"&gt;`&lt;/span&gt; |/ _ &lt;span class="se"&gt;\ &lt;/span&gt;|/ / |/ _&lt;span class="sb"&gt;`&lt;/span&gt; |
  s sssss  s             ___&lt;span class="o"&gt;)&lt;/span&gt; | | &lt;span class="o"&gt;(&lt;/span&gt;_| |  __/   &amp;lt;| | &lt;span class="o"&gt;(&lt;/span&gt;_| |
  ss    s  s            |____/|_|&lt;span class="se"&gt;\_&lt;/span&gt;_,_|&lt;span class="se"&gt;\_&lt;/span&gt;__|_|&lt;span class="se"&gt;\_\_&lt;/span&gt;|&lt;span class="se"&gt;\_&lt;/span&gt;_, |
  s     s s                                           |_|
        s s
       sss
       sss
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在另一个 Term 中使用 Rails Console 进行测试&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ rails c

# 调用perform
SmsWorker.perform_async 'Hello World', 0
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;就可以在 sidekiq 的调试窗口中看到输出了。&lt;/p&gt;
&lt;h2 id="Deploy with Capistrano"&gt;Deploy with Capistrano&lt;/h2&gt;
&lt;p&gt;添加 gem &lt;a href="https://github.com/seuros/capistrano-sidekiq" rel="nofollow" target="_blank" title=""&gt;capistrano-sidekiq&lt;/a&gt;添加到 Rails Project&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;'capistrano-sidekiq'&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;group: :development&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后，项目中运行'cap -vT'，可以看到添加下面这些有关 sidekiq 的命令。&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;cap&lt;/span&gt; &lt;span class="n"&gt;sidekiq&lt;/span&gt;&lt;span class="ss"&gt;:quiet&lt;/span&gt;                  &lt;span class="c1"&gt;# Quiet sidekiq (stop processing new tasks)&lt;/span&gt;
&lt;span class="n"&gt;cap&lt;/span&gt; &lt;span class="n"&gt;sidekiq&lt;/span&gt;&lt;span class="ss"&gt;:respawn&lt;/span&gt;                &lt;span class="c1"&gt;# Respawn missing sidekiq proccesses&lt;/span&gt;
&lt;span class="n"&gt;cap&lt;/span&gt; &lt;span class="n"&gt;sidekiq&lt;/span&gt;&lt;span class="ss"&gt;:restart&lt;/span&gt;                &lt;span class="c1"&gt;# Restart sidekiq&lt;/span&gt;
&lt;span class="n"&gt;cap&lt;/span&gt; &lt;span class="n"&gt;sidekiq&lt;/span&gt;&lt;span class="ss"&gt;:rolling_restart&lt;/span&gt;        &lt;span class="c1"&gt;# Rolling-restart sidekiq&lt;/span&gt;
&lt;span class="n"&gt;cap&lt;/span&gt; &lt;span class="n"&gt;sidekiq&lt;/span&gt;&lt;span class="ss"&gt;:start&lt;/span&gt;                  &lt;span class="c1"&gt;# Start sidekiq&lt;/span&gt;
&lt;span class="n"&gt;cap&lt;/span&gt; &lt;span class="n"&gt;sidekiq&lt;/span&gt;&lt;span class="ss"&gt;:stop&lt;/span&gt;                   &lt;span class="c1"&gt;# Stop sidekiq&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;(x)Cap 2.x 中可以配置 cmd 来选择 sidekiq.yml 进行启动，但 Cap 3.x 中就只能过配在 stage 下纯代码的方式来配置 (x)&lt;/em&gt;，后来问了下作者，sidekiq_config 就是用来在 3.x 中使用 yml 来启动的：&lt;/p&gt;

&lt;p&gt;以下为 cap-sidekiq 的参数配置和其默认值：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="ss"&gt;:sidekiq_default_hooks&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;  &lt;span class="kp"&gt;true&lt;/span&gt;
&lt;span class="ss"&gt;:sidekiq_pid&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;  &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;shared_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'tmp'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'pids'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'sidekiq.pid'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ss"&gt;:sidekiq_env&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;  &lt;span class="n"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:rack_env&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:rails_env&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:stage&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="ss"&gt;:sidekiq_log&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;  &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;shared_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'log'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'sidekiq.log'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ss"&gt;:sidekiq_options&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;  &lt;span class="kp"&gt;nil&lt;/span&gt;
&lt;span class="ss"&gt;:sidekiq_require&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;
&lt;span class="ss"&gt;:sidekiq_tag&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;
&lt;span class="ss"&gt;:sidekiq_config&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;
&lt;span class="ss"&gt;:sidekiq_queue&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;
&lt;span class="ss"&gt;:sidekiq_timeout&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;  &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;span class="ss"&gt;:sidekiq_role&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;  &lt;span class="ss"&gt;:app&lt;/span&gt;
&lt;span class="ss"&gt;:sidekiq_processes&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;  &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="ss"&gt;:sidekiq_concurrency&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;sidekiq_default_hooks 是 capistrano-sidekiq 提供的默认的 hooks，在 cap 的指定 task 前后指行相应的 task，如发布前关闭 sidekiq，发布完后启动 Sidekiq。具体见代码。如果不需要，可以设置该值为 false，即可关闭。&lt;/p&gt;
&lt;h3 id="Rails中的Cap配置示例："&gt;Rails 中的 Cap 配置示例：&lt;/h3&gt;
&lt;p&gt;示例如下，在 stage 中配置 concurrency pool size 和 named queue 的值&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;## sidekiq&lt;/span&gt;
&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:sidekiq_concurrency&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:sidekiq_queue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'client_sms,2'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'client_emails,5'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'default,3'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'foo'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;## or use config.yml file&lt;/span&gt;
&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:sidekiq_config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;current_path&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/config/sidekiq.yml"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;会启动如下命令：&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;RBENV_ROOT=~/.rbenv RBENV_VERSION=2.1.2 ~/.rbenv/bin/rbenv exec bundle exec sidekiq --index 0 --pidfile /home/ares/apps/highlander/shared/tmp/pids/sidekiq.pid --environment production --logfile /home/ares/apps/highlander/shared/log/sidekiq.log --queue sms, notification --concurrency 10 --daemon
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这里有一个问题，我第一天使用时，花了半天去调试，发现是'set pry'的问题 &lt;a href="https://github.com/seuros/capistrano-sidekiq/issues/23" rel="nofollow" target="_blank" title=""&gt;Not started sidekiq after deploy - if pty is true&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;当初忘记为什么，在 deploy.rb 中设置 pry 为 true 了，只好在 production stage 的配置中，设置回来。&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:pty&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="进程监控"&gt;进程监控&lt;/h2&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 查看sidekiq进程&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;ps aux | &lt;span class="nb"&gt;grep &lt;/span&gt;sidekiq
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="使用自带的监控页面"&gt;使用自带的监控页面&lt;/h4&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;'sinatra'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'sidekiq/web'&lt;/span&gt;
&lt;span class="n"&gt;mount&lt;/span&gt; &lt;span class="no"&gt;Sidekiq&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Web&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'/sidekiq'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这样，就可以在页面上看到 sidekiq 的运行情况了。更多详情见：&lt;a href="https://github.com/mperham/sidekiq/wiki/Monitoring" rel="nofollow" target="_blank" title=""&gt;sidekiq Monitoring&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="REF::"&gt;REF::&lt;/h2&gt;
&lt;p&gt;&lt;a href="http://railscasts.com/episodes/366-sidekiq?view=asciicast" rel="nofollow" target="_blank"&gt;http://railscasts.com/episodes/366-sidekiq?view=asciicast&lt;/a&gt;&lt;br&gt;
&lt;a href="http://stackoverflow.com/questions/14825565/sidekiq-deploy-to-multiple-environments" rel="nofollow" target="_blank"&gt;http://stackoverflow.com/questions/14825565/sidekiq-deploy-to-multiple-environments&lt;/a&gt;   &lt;/p&gt;</description>
      <author>lanvige</author>
      <pubDate>Thu, 12 Jun 2014 08:02:39 +0800</pubDate>
      <link>https://ruby-china.org/topics/19891</link>
      <guid>https://ruby-china.org/topics/19891</guid>
    </item>
    <item>
      <title>Capistrano 3 实现 Rails 自动化部署</title>
      <description>&lt;p&gt;原文始发：&lt;a href="http://lanvige.github.io/2014/02/21/using-capistrano-3-to-deploy/" rel="nofollow" target="_blank"&gt;http://lanvige.github.io/2014/02/21/using-capistrano-3-to-deploy/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src="//l.ruby-china.com/photo/2014/4d5934b7971d44edce2cc2b22a36f5c5.jpg" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;Offical Site: &lt;a href="http://capistranorb.com/" rel="nofollow" target="_blank"&gt;http://capistranorb.com/&lt;/a&gt;&lt;br&gt;
Github: &lt;a href="https://github.com/capistrano/capistrano" rel="nofollow" target="_blank"&gt;https://github.com/capistrano/capistrano&lt;/a&gt;      &lt;/p&gt;

&lt;p&gt;Capistrano 3.1 相对于之前的 2.x 有着很大不同，本想用自动化发布，应该是分分种搞定的事情，没想到找文档，看说明，花了一天也没看出个什么，于是晚上花时间把 2.x 和 3.1 的代码过了下，做了个对比，总算搞明白了里面的一些机制。&lt;/p&gt;
&lt;h5 id="使用版本"&gt;使用版本&lt;/h5&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;unicorn 4.8.2
rails 4.1.0
ruby 2.1.1
capistrano 3.1
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="安装::"&gt;安装::&lt;/h2&gt;
&lt;p&gt;在&lt;code&gt;Gemfile&lt;/code&gt;中添加 Capistrano 和其它用到的插件&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;group&lt;/span&gt; &lt;span class="ss"&gt;:development&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;'capistrano'&lt;/span&gt;
  &lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;'capistrano-bundler'&lt;/span&gt;
  &lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;'capistrano-rails'&lt;/span&gt;
  &lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;'capistrano-rbenv'&lt;/span&gt;
  &lt;span class="c1"&gt;# Add this if you're using rvm&lt;/span&gt;
  &lt;span class="c1"&gt;# gem 'capistrano-rvm'&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h5 id="项目中初始化 Capistrano"&gt;项目中初始化 Capistrano&lt;/h5&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cap install
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;会生成如下目录文件，&lt;code&gt;Capfile&lt;/code&gt;用来配置 Capistrano，&lt;code&gt;deploy.rb&lt;/code&gt;是一些共用 task 的定义，而&lt;code&gt;production.rb/staging.rb&lt;/code&gt;用来定义具体的 stage 的 tasks。&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;├── Capfile   
├── config   
│   ├── deploy   
│   │   ├── production.rb   
│   │   └── staging.rb   
│   └── deploy.rb   
└── lib   
    └── capistrano   
        └── tasks
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;安装完成之后，通过 &lt;code&gt;cap -vT&lt;/code&gt; 来查看当前项目的可执行任务列表。&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;cap&lt;/span&gt; &lt;span class="n"&gt;bundler&lt;/span&gt;&lt;span class="ss"&gt;:install&lt;/span&gt;                &lt;span class="c1"&gt;# Install the current Bundler environment&lt;/span&gt;
&lt;span class="n"&gt;cap&lt;/span&gt; &lt;span class="n"&gt;deploy&lt;/span&gt;                         &lt;span class="c1"&gt;# Deploy a new release&lt;/span&gt;
&lt;span class="n"&gt;cap&lt;/span&gt; &lt;span class="n"&gt;deploy&lt;/span&gt;&lt;span class="ss"&gt;:check&lt;/span&gt;                   &lt;span class="c1"&gt;# Check required files and directories exist&lt;/span&gt;
&lt;span class="n"&gt;cap&lt;/span&gt; &lt;span class="n"&gt;deploy&lt;/span&gt;&lt;span class="ss"&gt;:check:directories&lt;/span&gt;       &lt;span class="c1"&gt;# Check shared and release directories exist&lt;/span&gt;
&lt;span class="n"&gt;cap&lt;/span&gt; &lt;span class="n"&gt;deploy&lt;/span&gt;&lt;span class="ss"&gt;:check:linked_dirs&lt;/span&gt;       &lt;span class="c1"&gt;# Check directories to be linked exist in shared&lt;/span&gt;
&lt;span class="n"&gt;cap&lt;/span&gt; &lt;span class="n"&gt;deploy&lt;/span&gt;&lt;span class="ss"&gt;:check:linked_files&lt;/span&gt;      &lt;span class="c1"&gt;# Check files to be linked exist in shared&lt;/span&gt;
&lt;span class="n"&gt;cap&lt;/span&gt; &lt;span class="n"&gt;deploy&lt;/span&gt;&lt;span class="ss"&gt;:check:make_linked_dirs&lt;/span&gt;  &lt;span class="c1"&gt;# Check directories of files to be linked exist in shared&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="n"&gt;cap&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt;                        &lt;span class="c1"&gt;# Install Capistrano, cap install STAGES=staging,production&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这些命令其中就包括 刚刚执行的&lt;code&gt;cap install&lt;/code&gt;，其它用到的，后面再讲。&lt;/p&gt;
&lt;h2 id="配置 Capistrano"&gt;配置 Capistrano&lt;/h2&gt;&lt;h3 id="- 在Capfile里开启要用到的一些插件"&gt;- 在&lt;code&gt;Capfile&lt;/code&gt;里开启要用到的一些插件&lt;/h3&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'capistrano/setup'&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'capistrano/deploy'&lt;/span&gt;

&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'capistrano/rbenv'&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'capistrano/bundler'&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'capistrano/rails/assets'&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'capistrano/rails/migrations'&lt;/span&gt;

&lt;span class="no"&gt;Dir&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'lib/capistrano/tasks/*.cap'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;import&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;###&lt;/p&gt;

&lt;p&gt;本文件中用来配置共用变量。&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# config valid only for Capistrano 3.1&lt;/span&gt;
&lt;span class="n"&gt;lock&lt;/span&gt; &lt;span class="s1"&gt;'3.1.0'&lt;/span&gt;

&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:application&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'appname'&lt;/span&gt;
&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:deploy_user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'ares'&lt;/span&gt;

&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:scm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:git&lt;/span&gt;
&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:repo_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'git@github.org:lanvige/railsapp.git'&lt;/span&gt;

&lt;span class="c1"&gt;# rbenv&lt;/span&gt;
&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:rbenv_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:user&lt;/span&gt;
&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:rbenv_ruby&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'2.1.1'&lt;/span&gt;
&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:rbenv_prefix&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"RBENV_ROOT=&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:rbenv_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; RBENV_VERSION=&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:rbenv_ruby&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:rbenv_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/bin/rbenv exec"&lt;/span&gt;
&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:rbenv_map_bins&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sx"&gt;%w{rake gem bundle ruby rails}&lt;/span&gt;

&lt;span class="c1"&gt;# how many old releases do we want to keep, not much&lt;/span&gt;
&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:keep_releases&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;

&lt;span class="c1"&gt;# files we want symlinking to specific entries in shared&lt;/span&gt;
&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:linked_files&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sx"&gt;%w{config/database.yml config/application.yml config/secrets.yml}&lt;/span&gt;

&lt;span class="c1"&gt;# dirs we want symlinking to shared&lt;/span&gt;
&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:linked_dirs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sx"&gt;%w{bin log tmp/pids tmp/cache tmp/sockets vendor/bundle public/system}&lt;/span&gt;

&lt;span class="n"&gt;namespace&lt;/span&gt; &lt;span class="ss"&gt;:deploy&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;after&lt;/span&gt; &lt;span class="ss"&gt;:finishing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'deploy:cleanup'&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;rbenv 的配置见&lt;a href="https://github.com/capistrano/rbenv" rel="nofollow" target="_blank" title=""&gt;这里&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;linked_files &amp;amp; linked_dirs 见&lt;a href="#linked_detail" title=""&gt;这里&lt;/a&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="- 配置Stage"&gt;- 配置&lt;code&gt;Stage&lt;/code&gt;
&lt;/h3&gt;
&lt;p&gt;关于 Stage，&lt;a href="#stage_detail" title=""&gt;详见：&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;一个很重要的配置是 Role、Server（User）以及其对应关系，为了方便，Cap3 中提供了多种配置形式，各有不同的侧重，但用途都是一样的，见下面。&lt;/p&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="c1"&gt;# 以role为中心的写法&lt;/span&gt;
&lt;span class="k"&gt;role&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s"&gt;app,&lt;/span&gt; &lt;span class="s"&gt;%w&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kn"&gt;deploy@example.com,&lt;/span&gt; &lt;span class="s"&gt;deploy@example.local&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;
&lt;span class="s"&gt;role&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s"&gt;web,&lt;/span&gt; &lt;span class="s"&gt;%w&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kn"&gt;deploy@example.com&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;
&lt;span class="s"&gt;role&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s"&gt;db,&lt;/span&gt;  &lt;span class="s"&gt;%w&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kn"&gt;deploy@example.com&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# 以server为中心的写法，上面的写法可以用以下写法代替：&lt;/span&gt;
&lt;span class="s"&gt;server&lt;/span&gt; &lt;span class="s"&gt;'example.com',&lt;/span&gt; &lt;span class="s"&gt;user:&lt;/span&gt; &lt;span class="s"&gt;'deploy',&lt;/span&gt; &lt;span class="s"&gt;roles:&lt;/span&gt; &lt;span class="s"&gt;%w&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kn"&gt;web&lt;/span&gt; &lt;span class="s"&gt;app&lt;/span&gt; &lt;span class="s"&gt;db&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;
&lt;span class="s"&gt;server&lt;/span&gt; &lt;span class="s"&gt;'example.local',&lt;/span&gt; &lt;span class="s"&gt;user:&lt;/span&gt; &lt;span class="s"&gt;'deploy',&lt;/span&gt; &lt;span class="s"&gt;roles:&lt;/span&gt; &lt;span class="s"&gt;%w&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kn"&gt;app&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# 如果要对某服务器配置SSH等更多时，也可以用这种写法：&lt;/span&gt;
&lt;span class="s"&gt;server&lt;/span&gt; &lt;span class="s"&gt;'example.com',&lt;/span&gt;
  &lt;span class="s"&gt;user:&lt;/span&gt; &lt;span class="s"&gt;'user_name',&lt;/span&gt;
  &lt;span class="s"&gt;roles:&lt;/span&gt; &lt;span class="s"&gt;%w&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kn"&gt;web&lt;/span&gt; &lt;span class="s"&gt;app&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="s"&gt;,&lt;/span&gt;
  &lt;span class="s"&gt;ssh_options:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;user:&lt;/span&gt; &lt;span class="s"&gt;'user_name',&lt;/span&gt; &lt;span class="c1"&gt;# overrides user setting above&lt;/span&gt;
    &lt;span class="s"&gt;keys:&lt;/span&gt; &lt;span class="s"&gt;%w(/home/user_name/.ssh/id_rsa),&lt;/span&gt;
    &lt;span class="s"&gt;forward_agent:&lt;/span&gt; &lt;span class="s"&gt;false,&lt;/span&gt;
    &lt;span class="s"&gt;auth_methods:&lt;/span&gt; &lt;span class="s"&gt;%w(publickey&lt;/span&gt; &lt;span class="s"&gt;password)&lt;/span&gt;
    &lt;span class="c1"&gt;# password: 'please use keys'&lt;/span&gt;
  &lt;span class="err"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Stage 示例&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:stage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:test&lt;/span&gt;
&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:branch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'develop'&lt;/span&gt;

&lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="s1"&gt;'192.168.1.1'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;user: &lt;/span&gt;&lt;span class="s1"&gt;'ares'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;roles: &lt;/span&gt;&lt;span class="sx"&gt;%w{web app db}&lt;/span&gt;

&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:deploy_to&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"/home/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:deploy_user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/apps/appname"&lt;/span&gt;

&lt;span class="c1"&gt;# dont try and infer something as important as environment from&lt;/span&gt;
&lt;span class="c1"&gt;# stage name.&lt;/span&gt;
&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:rails_env&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:test&lt;/span&gt;

&lt;span class="c1"&gt;# number of unicorn workers, this will be reflected in&lt;/span&gt;
&lt;span class="c1"&gt;# the unicorn.rb and the monit configs&lt;/span&gt;
&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:unicorn_worker_count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;

&lt;span class="c1"&gt;# whether we're using ssl or not, used for building nginx&lt;/span&gt;
&lt;span class="c1"&gt;# config file&lt;/span&gt;
&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:enable_ssl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="开始部署::"&gt;开始部署::&lt;/h2&gt;&lt;h3 id="- 部署"&gt;- 部署&lt;/h3&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;cap production deploy &lt;span class="nt"&gt;--dry-run&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;cap production deploy
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;输入服务器用户密码后就 deploy 就进行了。不想每次都输密码，&lt;a href="#ssh-copy-id" title=""&gt;ssh-copy-id&lt;/a&gt;可能是你想要的。&lt;/p&gt;
&lt;h3 id="- 服务器生成目录详解"&gt;- 服务器生成目录详解&lt;/h3&gt;
&lt;p&gt;运行多次 deploy 之后会生成这样的目录结构：&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.
├── current -&amp;gt; /home/ares/apps/appname/releases/20140325071623
├── releases
│&amp;nbsp;&amp;nbsp; ├── 20140325065734
│&amp;nbsp;&amp;nbsp; ├── 20140325071310
│&amp;nbsp;&amp;nbsp; ├── 20140325071623
│&amp;nbsp;&amp;nbsp; └── 20140325074922
├── repo
│&amp;nbsp;&amp;nbsp; ├── branches
│&amp;nbsp;&amp;nbsp; ├── config
│&amp;nbsp;&amp;nbsp; ├── description
│&amp;nbsp;&amp;nbsp; ├── FETCH_HEAD
│&amp;nbsp;&amp;nbsp; ├── HEAD
│&amp;nbsp;&amp;nbsp; ├── hooks
│&amp;nbsp;&amp;nbsp; ├── info
│&amp;nbsp;&amp;nbsp; ├── objects
│&amp;nbsp;&amp;nbsp; ├── packed-refs
│&amp;nbsp;&amp;nbsp; └── refs
├── revisions.log
└── shared
    ├── bin
    ├── bundle
    ├── config
    ├── log
    ├── public
    ├── tmp
    └── vendor
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;release 每次发布都会产成一个目录，该目录下存放着 Rails 项目源码，多个目录是为了 rollback 而设。&lt;/li&gt;
&lt;li&gt;current 是指当前版本，软链接到 release 下的某个版本目录。&lt;/li&gt;
&lt;li&gt;repo 存的是项目的.git 目录&lt;/li&gt;
&lt;li&gt;shared 是项目中共享的内容，如 config 文件，不随每次发布而改动。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="- Rollback"&gt;- Rollback&lt;/h3&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cap production deploy:rollback
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Rollback 其实就是把 current 目录指向到 releases 里上次发布的目录。&lt;/p&gt;
&lt;h2 id="关键词解析::"&gt;关键词解析::&lt;/h2&gt;&lt;h3 id="- Cap Flow"&gt;- &lt;code&gt;Cap Flow&lt;/code&gt;
&lt;/h3&gt;
&lt;p&gt;系统默认包含下面的这些 Task，Task 是有顺序的，在每个 Task 之前和之后可以通过&lt;code&gt;before&lt;/code&gt;, &lt;code&gt;after&lt;/code&gt;添加自定义的 Task。更多 Flow 介绍，见&lt;a href="http://capistranorb.com/documentation/getting-started/flow/" rel="nofollow" target="_blank" title=""&gt;这里&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;deploy:starting&lt;br&gt;
&lt;/li&gt;
&lt;li&gt;deploy:started&lt;br&gt;
&lt;/li&gt;
&lt;li&gt;deploy:reverting           - revert server(s) to previous release&lt;br&gt;
&lt;/li&gt;
&lt;li&gt;deploy:reverted            - reverted hook&lt;br&gt;
&lt;/li&gt;
&lt;li&gt;deploy:publishing&lt;br&gt;
&lt;/li&gt;
&lt;li&gt;deploy:published&lt;br&gt;
&lt;/li&gt;
&lt;li&gt;deploy:finishing_rollback  - finish the rollback, clean up everything&lt;br&gt;
&lt;/li&gt;
&lt;li&gt;deploy:finished&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;在这些 Flow 之外也有一些常用的 Task：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;##### deploy:check
对应 Cap 2.x 中的 deploy:setup。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;check 不属于 deploy flow，它的目的主要是在服务器上创建所需要的目录（主要是 shared, release），然后就是对应的 linked_dir &amp;amp; linked_files 操作。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;h5 id="deploy:cold in 2.x"&gt;deploy:cold in 2.x&lt;/h5&gt;
&lt;p&gt;新的系统中，核心的 deploy task 是幂等 (idempotent) 的，所以像&lt;code&gt;cap deploy:cold&lt;/code&gt;这样的预执行命令（创建目录结构）就不再被需要了。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h5 id="dry run"&gt;dry run&lt;/h5&gt;
&lt;p&gt;dry-run 主要是保证每一个命令都能被执行到，但不会在服务器上产生任何改动。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;cap production deploy —dry-run
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="- Stage"&gt;- Stage&lt;/h3&gt;
&lt;p&gt;Cap 中有和 Rails 一样的运行环境（&lt;code&gt;Environment&lt;/code&gt;）的概念 (Cap 中叫作&lt;code&gt;Stage&lt;/code&gt;，默认建了 2 个 Stage，&lt;code&gt;staging&lt;/code&gt;, &lt;code&gt;production&lt;/code&gt;），就是不同环境下对应不同的服务器。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;deploy.rb&lt;/code&gt;中定义着公用的变量，对应到不同的 Stage，可以定义一些专有的变量，同时也可以覆写 deploy.rb 中的公用变量。&lt;/p&gt;

&lt;p&gt;注：Stage 名字默认对应 Rails 的 environment 名字（&lt;code&gt;development&lt;/code&gt;, &lt;code&gt;test&lt;/code&gt;, &lt;code&gt;production&lt;/code&gt;）。可通过设置进行映射。&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;set :rails_env, :test
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="- linked_files &amp;amp; linked_dirs"&gt;- &lt;code&gt;linked_files&lt;/code&gt; &amp;amp; &lt;code&gt;linked_dirs&lt;/code&gt;
&lt;/h3&gt;
&lt;p&gt;Capistrano 使用&lt;code&gt;Shared&lt;/code&gt;目录来管理那些在不同&lt;code&gt;Release&lt;/code&gt;中共用的文件，最主要的一个&lt;code&gt;shared/config&lt;/code&gt;中包含每个发布所需要的配置文件&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;##### linked_dirs
是将项目的指定目录链接到 shared 目录中。这个操作会在从 repo 取下代码之后进行。&lt;/li&gt;
&lt;li&gt;##### linked_files
和 linked_dirs 相反，它是将 shared 中的文件链接到项目中，文件要首先存在于 shared 目录中，不然 deploy 时会报错。
Rails 项目中，主要就是&lt;code&gt;database.yml&lt;/code&gt;，&lt;code&gt;secret.yml&lt;/code&gt;这样的敏感文件。对于这些文件最好的做法就是从 Git 中过滤掉，然后每个开发者和服务器都单独配置。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="- MySQL"&gt;- MySQL&lt;/h3&gt;
&lt;p&gt;在尝试使用 SQLite3 进行 Cap 测试通过后，将 DB 换成 MySQL，然后又出错了。错误是数据库不存在，一直以为是在创建数据库时未指定&lt;code&gt;RAILS_EVN&lt;/code&gt;，后来发现 migrations 在执行前也没有运行&lt;code&gt;db:create&lt;/code&gt;来创建数据库。&lt;/p&gt;

&lt;p&gt;在运行 deploy 前，自己手工创建数据库，然后 deploy 就能正常运行了。猜想：create 属于一次性操作，所以没有将其作为 task 放入 deploy 中。&lt;/p&gt;
&lt;h3 id="- Ask"&gt;- Ask&lt;/h3&gt;
&lt;p&gt;在 deploy.rb 和 stage 文件中，我们可以设置变量的值。但有时，值会在运行时才被确定，这样就可以通过 ask 来设定。&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ask :branch, ‘my_default_branch’
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这样在 branch 变量第一次被使用时，会有输入提示，就可以动态设置该值了。&lt;/p&gt;
&lt;h3 id="- Role"&gt;- Role&lt;/h3&gt;
&lt;p&gt;角色的目的是让 Task 可以运行在不同的机器上。&lt;a href="http://stackoverflow.com/questions/1155218/what-exactly-is-a-role-in-capistrano" rel="nofollow" target="_blank" title=""&gt;更多&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;一个线上程序中有着多种服务器，像 DB Server, APP server, Web Server，在不同的 Server 上要运行不同的部署方案。Cap 也把这些也考虑到了，可以通过创建不同的 Role 来对这些服务器进行归类，为 Task 指定 Role 来运行。&lt;/p&gt;
&lt;h3 id="- Tasks"&gt;- Tasks&lt;/h3&gt;
&lt;p&gt;如何自定义 task&lt;a href="https://github.com/capistrano/capistrano/wiki/Capistrano-Tasks" rel="nofollow" target="_blank" title=""&gt;doc&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="- Cold Start"&gt;- Cold Start&lt;/h3&gt;
&lt;p&gt;可以在发布进行之前做一些准备工作，比如，创建 linked_files、Unicorn、Nginx 的配置及创建 Service 的工作。&lt;/p&gt;

&lt;p&gt;现行的作法是，定制一个 task，在 Deploy 之前进行，在服务器创建目录，然后从本地将文件预先&lt;a href="https://github.com/capistrano/sshkit/blob/master/EXAMPLES.md#upload-a-file-from-disk" rel="nofollow" target="_blank" title=""&gt;upload!&lt;/a&gt;) 到服务器的相应目录（主要是&lt;code&gt;shared/config&lt;/code&gt;）。&lt;/p&gt;
&lt;h3 id="- sudo"&gt;- sudo&lt;/h3&gt;
&lt;p&gt;Capistrano 3 推荐使用 passwordless sudo。这样非 root 用户也可以直接使用 sudo 命令，而不必通过 PTY 来输入密码。&lt;a href="http://www.capistranorb.com/documentation/getting-started/authentication-and-authorisation/#toc_8" rel="nofollow" target="_blank" title=""&gt;Guide:&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;其实就是在系统里，给指定用户赋上某些指令的 sudo 权限。在 Ubuntu 下，修改 &lt;code&gt;/etc/sudoers&lt;/code&gt;来添加要使用的命令。&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ares ALL=NOPASSWD:/usr/sbin/service, /bin/ln
#也可以将所有程序都设置为不要密码，不过太不安全，不建议
#ares ALL=(ALL) NOPASSWD: ALL
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="- PTYs"&gt;- PTYs&lt;/h3&gt;
&lt;p&gt;PTY 就是让用户在当前 Terminal 中执行任务时，可以进行交互。比如说执行 sudo 任务时，可以远程输入密码。 &lt;a href="https://github.com/capistrano/capistrano/blob/master/README.md#a-word-about-ptys" rel="nofollow" target="_blank" title=""&gt;更多&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ps：试着启用 pts，但输入密码后无反应。&lt;/p&gt;
&lt;h3 id="- ssh-copy-id"&gt;- ssh-copy-id&lt;/h3&gt;
&lt;p&gt;每次运行 cap 都要输入密码，可以将本地的 ssh 公钥存到 server 上，就可以省下很多时间。&lt;/p&gt;

&lt;p&gt;ssh-copy-id 就是这么一个将本机的公钥复制到远程机器的 authorized_keys 文件的工具，其也能让你拥有远程机器的 home, ~./ssh , 和 ~/.ssh/authorized_keys 的权利。&lt;/p&gt;

&lt;p&gt;首先本地机器上要创建 ssh key&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ssh-keygen
&lt;/code&gt;&lt;/pre&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ssh-copy-id ares@192.168.1.1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Mac OSX 上 ssh-copy-id 不是默认安装的，可通过 Homebrew 进行安装&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ brew install ssh-copy-id
&lt;/code&gt;&lt;/pre&gt;</description>
      <author>lanvige</author>
      <pubDate>Tue, 15 Apr 2014 14:25:11 +0800</pubDate>
      <link>https://ruby-china.org/topics/18616</link>
      <guid>https://ruby-china.org/topics/18616</guid>
    </item>
    <item>
      <title>问：二级目录换成二级域名的方案？</title>
      <description>&lt;p&gt;Rails 3 项目的 api 之前是放在 &lt;a href="http://www.myapp.com/api/v1/" rel="nofollow" target="_blank"&gt;http://www.myapp.com/api/v1/&lt;/a&gt; 下的，
现在想换成二级域名，像 &lt;a href="http://api.myapp.com/v1" rel="nofollow" target="_blank"&gt;http://api.myapp.com/v1&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;有好的解决方案吗？&lt;/p&gt;

&lt;p&gt;理论上 api 和 www 是同一套代码，能想到的也就是重做一个 router，将路径重定向。&lt;/p&gt;

&lt;p&gt;不知谁有这方面的经验。&lt;/p&gt;</description>
      <author>lanvige</author>
      <pubDate>Wed, 18 Jul 2012 13:23:39 +0800</pubDate>
      <link>https://ruby-china.org/topics/4388</link>
      <guid>https://ruby-china.org/topics/4388</guid>
    </item>
    <item>
      <title>NYC 逛街时看到的一家店 Ruby Tuesday</title>
      <description>&lt;p&gt;44 街吧，走着走着忽然备感亲切。&lt;/p&gt;

&lt;p&gt;&lt;img src="//l.ruby-china.com/photo/c8a8de4b218435c6122e9385ccca43f2.jpg" title="" alt=""&gt;&lt;/p&gt;</description>
      <author>lanvige</author>
      <pubDate>Tue, 03 Jul 2012 15:31:03 +0800</pubDate>
      <link>https://ruby-china.org/topics/4105</link>
      <guid>https://ruby-china.org/topics/4105</guid>
    </item>
    <item>
      <title>Ubuntu 中使用 Gmail 发送邮件需要安装 mutt 之类的工具吗？</title>
      <description>&lt;p&gt;我使用 Devise，用户注册时会发一个激活信息，目前使用 Gmail 作 Mail Server。&lt;/p&gt;

&lt;p&gt;这段代码在 OS X 上工作正常，但在 Ubuntu 11.04 X64 下，邮件就是发送不出来，也没有任何错误，Dev log 中也没其它信息。&lt;/p&gt;

&lt;p&gt;查到这么一个帖子，和我问题较相似：
&lt;a href="http://stackoverflow.com/questions/8498586/rails-mailer-ubuntu" rel="nofollow" target="_blank"&gt;http://stackoverflow.com/questions/8498586/rails-mailer-ubuntu&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;装了 mutt 这样的 mail agent，但似乎问题依旧。&lt;/p&gt;

&lt;p&gt;Ubuntu 上还要配其它东西吗？  &lt;/p&gt;</description>
      <author>lanvige</author>
      <pubDate>Thu, 05 Jan 2012 19:55:13 +0800</pubDate>
      <link>https://ruby-china.org/topics/748</link>
      <guid>https://ruby-china.org/topics/748</guid>
    </item>
  </channel>
</rss>
