<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>qhwa</title>
    <link>https://ruby-china.org/qhwa</link>
    <description></description>
    <language>en-us</language>
    <item>
      <title> (Elixir 小程序) Tower2slack -- 让 Tower 的 hook 支持 Slack</title>
      <description>&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/2016/f8cb088cc16ffc7138401127880a108e.png!large" width="300px" alt=""&gt;&lt;/p&gt;

&lt;p&gt;我们团队使用 &lt;a href="https://tower.io" rel="nofollow" target="_blank" title=""&gt;Tower&lt;/a&gt; + &lt;a href="https://slack.com" rel="nofollow" target="_blank" title=""&gt;Slack&lt;/a&gt; 作为日常的协作工具。
tower 提供了 web hook 的功能，可以将发生的事件通知给其他应用。Slack 也有 incomming bot 可以接收消息，自动发给团队成员。
理论上可以很好工作的，但两者的数据定义不一样，需要中间做一次格式转换。&lt;/p&gt;

&lt;p&gt;因此我写了一个小服务，可以很作为一个 hook 代理，将收到的 notification 数据转换后发给 Slack.
项目地址：&lt;a href="https://github.com/qhwa/tower2slack" rel="nofollow" target="_blank"&gt;https://github.com/qhwa/tower2slack&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="使用方式"&gt;使用方式&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;根据 readme 启动服务。&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;将 tower 项目的 web hook url 设置为你服务器提供的 http 地址。
假设你的 slack incoming web hook 地址是&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://hooks.slack.com/services/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
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;那么就换成&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://YOUR_HOST:14326/services/T28DCF96F/BEFGB0UJD/Ge0s8ue2iOPkEtLLMv1uqfF8
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tower 的 web hook 设置中，secret 一栏可以填 &lt;code&gt;#频道名&lt;/code&gt; 或 &lt;code&gt;@用户名&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="效果图"&gt;效果图&lt;/h2&gt;
&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/2016/11dde9cb0c846d4da8199a8485374493.png!large" width="400px" alt=""&gt;&lt;/p&gt;
&lt;h2 id="友情提示"&gt;友情提示&lt;/h2&gt;
&lt;p&gt;由于国内、外网络原因，最好将服务部署到国外，这样网络方面的失败率会低一些。&lt;/p&gt;</description>
      <author>qhwa</author>
      <pubDate>Sat, 24 Sep 2016 22:13:12 +0800</pubDate>
      <link>https://ruby-china.org/topics/31160</link>
      <guid>https://ruby-china.org/topics/31160</guid>
    </item>
    <item>
      <title>Ruby 2.3 new feature 之一:  多行字符串更优美的写法</title>
      <description>&lt;h2 id="多行字符串的现状"&gt;多行字符串的现状&lt;/h2&gt;
&lt;p&gt;目前的 ruby ( &amp;lt;= 2.3 preview 1) 中，如果要写一个多行的字符串，是比较麻烦的。&lt;/p&gt;

&lt;p&gt;比如&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;hello&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;-&lt;/span&gt;&lt;span class="no"&gt;HEREDOC&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="sh"&gt;
    I know I know
    You will like it.
&lt;/span&gt;&lt;span class="no"&gt;  HEREDOC&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;hello&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;输出是 &lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;I know I know
You will like it.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;前面多了空格！&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;为了去掉空格，代码就会变得很丑：&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;hello&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;-&lt;/span&gt;&lt;span class="no"&gt;HEREDOC&lt;/span&gt;&lt;span class="sh"&gt;
I know I know
You will like it.
&lt;/span&gt;&lt;span class="no"&gt;  HEREDOC&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;hello&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;或者引入 &lt;a href="http://guides.rubyonrails.org/active_support_core_extensions.html#strip-heredoc" rel="nofollow" target="_blank" title=""&gt;active_support strip_heredoc&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;总之可以是做到，只是很不方便。&lt;/p&gt;
&lt;h2 id="Ruby 2.3 &lt;&lt;~"&gt;Ruby 2.3 &amp;lt;&amp;lt;~&lt;/h2&gt;
&lt;p&gt;ruby 2.3 将会引入一个新的语法 &lt;code&gt;&amp;lt;&amp;lt;~&lt;/code&gt; (squiggly heredoc)，让你用了就回不去&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;hello&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;~&lt;/span&gt;&lt;span class="no"&gt;HEREDOC&lt;/span&gt;&lt;span class="sh"&gt;
    I know I know
    You will like it.
&lt;/span&gt;&lt;span class="no"&gt;  HEREDOC&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;hello&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;完美输出：&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;I know I know
You will like it.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;yeah~&lt;/p&gt;</description>
      <author>qhwa</author>
      <pubDate>Wed, 23 Dec 2015 16:20:57 +0800</pubDate>
      <link>https://ruby-china.org/topics/28501</link>
      <guid>https://ruby-china.org/topics/28501</guid>
    </item>
    <item>
      <title>ruby.taobao.org 要强制使用 https 协议了</title>
      <description>&lt;p&gt;http 协议不安全，有被中间人篡改的可能性，所以 10 月 1 日起将强制使用 https 协议，http 协议会停止。&lt;/p&gt;

&lt;p&gt;SSL (https) 的服务不影响，如果你本来就已经在用 https，就不用关心这件事了。&lt;/p&gt;

&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/2015/9e952287b84f4a2fa86cfdd57ace3d3a.png" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;请检查配置中是否用了 http 协议：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;code&gt;Gemfile&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;~/.gemrc&lt;/code&gt; , &lt;code&gt;/etc/gemrc&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;~/.bundle/config&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;</description>
      <author>qhwa</author>
      <pubDate>Mon, 21 Sep 2015 08:43:09 +0800</pubDate>
      <link>https://ruby-china.org/topics/27412</link>
      <guid>https://ruby-china.org/topics/27412</guid>
    </item>
    <item>
      <title>无需更改 Gemfile，让 bundle 使用淘宝源</title>
      <description>&lt;p&gt;大家都知道 Gemfile 中可以指定源：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Gemfile:&lt;/span&gt;
&lt;span class="n"&gt;source&lt;/span&gt; &lt;span class="s1"&gt;'https://ruby.taobao.org'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然而有时候会带来些烦恼：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;自己做的开源项目，Gemfile 指定了用淘宝源，结果老外 git clone 过去用，发现杯具了&lt;/li&gt;
&lt;li&gt;需要国内、国外都部署，Gemfile 怎么写？&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="我今天知道，有个更方便的方法："&gt;我今天知道，有个更方便的方法：&lt;/h3&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Gemfile: 保持官方源不改&lt;/span&gt;
&lt;span class="n"&gt;source&lt;/span&gt; &lt;span class="s1"&gt;'https://rubygems.org'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;命令行中运行：&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bundle config &lt;span class="s1"&gt;'mirror.https://rubygems.org'&lt;/span&gt; &lt;span class="s1"&gt;'https://ruby.taobao.org'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;配置全局有效，所以只需要运行一次，新项目（例如 &lt;code&gt;rails new&lt;/code&gt;）都不用关心这个问题了&lt;/p&gt;

&lt;p&gt;感谢 &lt;a href="https://github.com/stevendaniels" rel="nofollow" target="_blank" title=""&gt;steven daniels&lt;/a&gt; &lt;a href="https://github.com/alibaba/ruby.taobao.org/pull/6" rel="nofollow" target="_blank" title=""&gt;提供&lt;/a&gt;!&lt;/p&gt;</description>
      <author>qhwa</author>
      <pubDate>Fri, 03 Jul 2015 15:30:07 +0800</pubDate>
      <link>https://ruby-china.org/topics/26314</link>
      <guid>https://ruby-china.org/topics/26314</guid>
    </item>
    <item>
      <title>[杭州] 阿里巴巴招聘 Ruby 工程师 2 名</title>
      <description>&lt;h3 id="招聘要求"&gt;招聘要求&lt;/h3&gt;
&lt;p&gt;阿里巴巴评级 P6 以上的职位，什么是 P6？&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;能独立完成产品功能开发；&lt;/li&gt;
&lt;li&gt;3 年以上 Ruby on Rails 开发经验；&lt;/li&gt;
&lt;li&gt;熟悉各种数据库，以 MySQL 为主；&lt;/li&gt;
&lt;li&gt;熟悉前端开发，能独立完成 HTML、CSS、JavaScript 的工作，能实现复杂的前端功能；&lt;/li&gt;
&lt;li&gt;熟悉 Linux 环境、运维相关内容；&lt;/li&gt;
&lt;li&gt;当然能否通过还是要看面试了解细节。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="待遇相关"&gt;待遇相关&lt;/h3&gt;
&lt;p&gt;&lt;img src="https://campus.alibaba.com/assets/campus/images/salary.jpg" title="" alt="salary"&gt;&lt;/p&gt;
&lt;h4 id="现金薪酬"&gt;现金薪酬&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;薪资&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;阿里巴巴集团为员工提供行业富有竞争力的薪资&lt;/li&gt;
&lt;li&gt;薪资根据每个人的能力不同。2015 年 P6 约 19k+，供参考，具体数字以最终 offer 为准&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;奖金&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;根据部门和个人的年度绩效，有不同档次的年终奖金&lt;/li&gt;
&lt;li&gt;优秀员工奖金更丰厚&lt;/li&gt;
&lt;li&gt;如果整体部门表现优异，会有特别奖励&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="长期奖励"&gt;长期奖励&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;根据员工的年度绩效，奖励优秀员工绩效股权&lt;/li&gt;
&lt;li&gt;年度表现优秀者，还有不同类型的特殊奖励&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="福利"&gt;福利&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;五险一金&lt;/strong&gt;: 都是按当地最高标准缴纳&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;iHome&lt;/strong&gt;: 为员工提供免息购房贷款，可用作首付&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;蒲公英计划&lt;/strong&gt;: 在员工及家庭（配偶、子女）面临重疾、残疾或身故的时候给予最高 20 万的经济援助&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;团队旅游&lt;/strong&gt;: 每年一次 outing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;孕妇休息室&lt;/strong&gt;: 为准妈妈提供舒适隐秘休息室，有舒服的沙发，有用心的布置&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;幸福班车&lt;/strong&gt;: 每周五和周一提供往返杭州和上海的幸福班车&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;配套设施&lt;/strong&gt;: 园区内有健身房、图书馆、星巴克等 &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;年休假&lt;/strong&gt;: 试用期即可以享受年假，第一年/第二年是 7 天，以后逐年增加 2 天，最多 15 天&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;路途假&lt;/strong&gt;: 为探望异地的父母、配偶，每年提供一次最长 3 天的路途假&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;年度体检&lt;/strong&gt;: 一年一度的免费体检，全面检测身体状况，尽早预防各类健康风险。同时还为家属提供了阿里折扣价（比外部团购价优惠）&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="成长"&gt;成长&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;有完善的晋升体系，可以一直做技术。可以根据自己的情况选择钻研技术、产品还是管理。&lt;/li&gt;
&lt;li&gt;有各类丰富的技术分享和培训课程，各种业务沉淀的技术都会面向内部进行分享。如果有心，能在这里学习到很多技术&lt;/li&gt;
&lt;li&gt;如果有意在产品方向发展的，也可以开发自己的创新产品。有专门的赛马计划进行鼓励&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="工作内容以及这边情况"&gt;工作内容以及这边情况&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;之前负责 &lt;a href="https://kanbox.com" rel="nofollow" target="_blank" title=""&gt;酷盘&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;目前这边的业务是 云 OS 相册服务。为个人用户提供好用的照片服务，涉及到照片智能识别分类、整理，高 QPS 性能优化等有挑战的工作。&lt;/li&gt;
&lt;li&gt;团队目前有 5 人，都使用 ruby 作为主要开发语言。之前是李华顺在负责，现在是我在负责。&lt;/li&gt;
&lt;li&gt;基本上每周五都有团队内部的技术分享。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="工作环境"&gt;工作环境&lt;/h3&gt;
&lt;p&gt;&lt;img src="https://img.alicdn.com/tps/TB1qlpsIpXXXXc6XpXXXXXXXXXX.jpg_q90.jpg" title="" alt="工作环境"&gt;
&lt;img src="https://img.alicdn.com/tps/TB1mtXyIpXXXXXKXpXXXXXXXXXX.png" title="" alt="工作环境"&gt;
&lt;img src="https://img.alicdn.com/tps/TB15mBzIpXXXXcBXXXXXXXXXXXX.jpg_q90.jpg" title="" alt="工作环境"&gt;
&lt;img src="https://img.alicdn.com/tps/TB1.tByIpXXXXXBXpXXXXXXXXXX.png" title="" alt="工作环境"&gt;
&lt;img src="https://img.alicdn.com/tps/TB10gxeIpXXXXbYXVXXXXXXXXXX.jpg_q90.jpg" title="" alt="工作环境"&gt;&lt;/p&gt;

&lt;p&gt;目前有 2 个名额！&lt;/p&gt;

&lt;p&gt;简历请发往：hua.qiuh[at]alibaba-inc.com&lt;/p&gt;</description>
      <author>qhwa</author>
      <pubDate>Tue, 16 Jun 2015 11:32:25 +0800</pubDate>
      <link>https://ruby-china.org/topics/26044</link>
      <guid>https://ruby-china.org/topics/26044</guid>
    </item>
    <item>
      <title>一个小 gem，协助选择集群中一部分服务器部署</title>
      <description>&lt;p&gt;想必大家都用过 &lt;a href="http://capistranorb.com/" rel="nofollow" target="_blank" title=""&gt;capistrano&lt;/a&gt; 了，部署代码到多个服务器上的神器。
不过使用中有个不太方便的地方是，某些情况下只想部署到其中几台。
有好几种方式可以做到：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;临时修改发布脚本（&lt;code&gt;config/deploy.rb&lt;/code&gt; 或 &lt;code&gt;config/deploy/***.rb&lt;/code&gt;）&lt;/li&gt;
&lt;li&gt;使用 &lt;code&gt;HOST&lt;/code&gt; 命令行环境变量，或者 &lt;code&gt;--host&lt;/code&gt; 参数，比如 &lt;code&gt;HOST=example.com cap production deploy&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;第 1 种不好重用，第 2 种在 &lt;a href="http://capistranorb.com/" rel="nofollow" target="_blank" title=""&gt;capistrano&lt;/a&gt; v3.3 以上版本已经失效了。&lt;/p&gt;

&lt;p&gt;我把我们项目中用的 task 抽出来做成了一个 gem: &lt;a href="https://github.com/qhwa/capistrano-hostmenu" rel="nofollow" target="_blank" title=""&gt;capistrano-hostmenu&lt;/a&gt;
功能实在是太简单，没有什么好描述的。。&lt;/p&gt;

&lt;p&gt;一图顶千言：&lt;/p&gt;

&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/2015/fd0dc13527ea01a9c5461ddc2b37638a.png" title="" alt=""&gt;&lt;/p&gt;</description>
      <author>qhwa</author>
      <pubDate>Tue, 03 Feb 2015 14:43:36 +0800</pubDate>
      <link>https://ruby-china.org/topics/24091</link>
      <guid>https://ruby-china.org/topics/24091</guid>
    </item>
    <item>
      <title>用 Ruby 开发命令行工具的一些 tips</title>
      <description>&lt;p&gt;最近 @季子乌 的 &lt;a href="http://huaban.com/pigeonzhu" rel="nofollow" target="_blank" title=""&gt;花瓣账号&lt;/a&gt; 突然被封，苦心采集的很多图片一下子全部看不到了！&lt;/p&gt;

&lt;p&gt;后来虽然联系客服重新开通了账号，但还是心有余悸，觉得还是 &lt;a href="http://www.pinterest.com/" rel="nofollow" target="_blank" title=""&gt;pinterest&lt;/a&gt; 靠谱一些，准备把图片全部迁移到 pinterest 上。由于图片数量比较多，我就用 ruby 写了一个工具，将花瓣上的图片下载下来。（不过 pinterest 不能批量上传，这些图片也只是备份到本地，这是后话了）&lt;/p&gt;

&lt;p&gt;这个项目已开源，地址是：
&lt;a href="https://github.com/qhwa/huaban_exporter" rel="nofollow" target="_blank"&gt;https://github.com/qhwa/huaban_exporter&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;这个工具下载后，可以用执行 &lt;code&gt;huaban&lt;/code&gt; 命令&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;huaban &lt;span class="nb"&gt;export &lt;/span&gt;boards &lt;span class="nt"&gt;--of&lt;/span&gt; qhwa
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;执行效果：&lt;/p&gt;

&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/2014/c804294a5c7101502c6938b4f47ebcde.gif" title="" alt="preview"&gt;&lt;/p&gt;

&lt;p&gt;我喜欢用命令行工作，之前做的几个 gem（&lt;a href="https://github.com/qhwa/lfd" rel="nofollow" target="_blank" title=""&gt;lfd&lt;/a&gt;, &lt;a href="https://github.com/qhwa/fdlint" rel="nofollow" target="_blank" title=""&gt;fdlint&lt;/a&gt;）也都提供了命令行。这次就趁这个项目总结了一下怎样用 ruby 开发友好的命令行工具。&lt;/p&gt;
&lt;h3 id="I. 初期怎样提高开发效率？"&gt;I. 初期怎样提高开发效率？&lt;/h3&gt;
&lt;p&gt;在写了基础的一些逻辑 model 后，我写个简单的 &lt;a href="https://github.com/qhwa/huaban_exporter/blob/69b16009357a87f2e6e645801694a16b65803a41/Rakefile" rel="nofollow" target="_blank" title=""&gt;rake 文件&lt;/a&gt;，初期用 rake 来作为入口，边开发边测试。&lt;/p&gt;

&lt;p&gt;一开始我只建了这样的一个 rake 任务，来调试获取画板列表功能：&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rake boards         &lt;span class="c"&gt;# 列出一个用户的所有画板 (user=用户名 rake boards)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;后来随着功能不断完成，逐渐增加了几个新的任务，最后是完整的任务：&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rake boards         &lt;span class="c"&gt;# 列出一个用户的所有画板 (user=用户名 rake boards)&lt;/span&gt;
rake export_board   &lt;span class="c"&gt;# 导出一个画板的所有图片到本地 (board_id=画板id  rake export_board)&lt;/span&gt;
rake export_boards  &lt;span class="c"&gt;# 导出用户所有的画板图片到本地 (user=用户名 rake export_boards)&lt;/span&gt;
rake pins           &lt;span class="c"&gt;# 列出一个画板所有的采集 (board_id=画板id rake pins)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="II. 项目后期功能稳定后，怎么做命令行入口"&gt;II. 项目后期功能稳定后，怎么做命令行入口&lt;/h3&gt;
&lt;p&gt;rakefile 很适合自己用，但是要分发别人用，用 rakefile 就不方便了。做成带命令行脚本的 gem 更加方便。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;把你的脚本放到 &lt;code&gt;bin&lt;/code&gt; 目录下&lt;/li&gt;
&lt;li&gt;加上执行权限 (&lt;code&gt;chmod a+x&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;加上 &lt;a href="http://zh.wikipedia.org/zh-cn/Shebang" rel="nofollow" target="_blank" title=""&gt;shebang&lt;/a&gt;, 比如 &lt;code&gt;#!/usr/bin/env ruby&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;这一步我以前是用下面提到的 gli 来自动进行，但后来改成手动做了。因为 gli 生成了一些额外的文件，和 bundle 有点冲突。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="III. 怎样让命令变得友好?"&gt;III. 怎样让命令变得友好？&lt;/h3&gt;
&lt;p&gt;有个超棒的 gem 叫做 [gli][gli]，帮你很容易实现出类似 git 这样风格的脚本&lt;/p&gt;
&lt;h3 id="IV. 项目完成后，怎么用做成一个 gem，分享给别人?"&gt;IV. 项目完成后，怎么用做成一个 gem，分享给别人？&lt;/h3&gt;
&lt;p&gt;[bundler][bundler] 提供了生成 gem 的功能&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;bundle gem &amp;lt;name&amp;gt;&lt;/code&gt; 生成目录结构&lt;/li&gt;
&lt;li&gt;修改 gemspec&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;rake install&lt;/code&gt; 先在本地安装这个 gem 进行测试&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;rake build&lt;/code&gt;   以最新的文件重新打包成 gem&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;rake release&lt;/code&gt;  打包成 gem, 生成 git tag，将 gem 上传到 &lt;a href="https://rubygems.org" rel="nofollow" target="_blank"&gt;https://rubygems.org&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;[huaban]: &lt;a href="http://www.huaban.com" rel="nofollow" target="_blank"&gt;http://www.huaban.com&lt;/a&gt;
[proj]: &lt;a href="https://github.com/qhwa/huaban_exporter" rel="nofollow" target="_blank"&gt;https://github.com/qhwa/huaban_exporter&lt;/a&gt;
[gli]: &lt;a href="https://github.com/davetron5000/gli" rel="nofollow" target="_blank"&gt;https://github.com/davetron5000/gli&lt;/a&gt;
[bundler]: &lt;a href="http://bundler.io/" rel="nofollow" target="_blank"&gt;http://bundler.io/&lt;/a&gt;&lt;/p&gt;</description>
      <author>qhwa</author>
      <pubDate>Mon, 17 Nov 2014 12:53:38 +0800</pubDate>
      <link>https://ruby-china.org/topics/22714</link>
      <guid>https://ruby-china.org/topics/22714</guid>
    </item>
    <item>
      <title>MRuby 1.0 发布了</title>
      <description>&lt;p&gt;&lt;img src="http://www.mruby.org/images/mruby_logo_red_icon.png" title="" alt="Mruby"&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.mruby.org/" rel="nofollow" target="_blank" title=""&gt;Mruby&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;看 libraries，已经有很多有趣又有用的库了。比如：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/ppibburr/mruby-girffi" rel="nofollow" target="_blank" title=""&gt;mruby-girffi&lt;/a&gt; 可以用来对接现有的 C 库&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/mobiruby/mruby-cocoa" rel="nofollow" target="_blank" title=""&gt;cocoa&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/kyab/mruby-arduino" rel="nofollow" target="_blank" title=""&gt;arduino&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;redis  &lt;a href="http://lucaguidi.com/2014/02/26/redis-scripting-with-mruby-pt1.html" rel="nofollow" target="_blank" title=""&gt;作为 redis 脚本&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;gtk2 / gtk3 / fltk ...
...&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;个人认为最近硬件发展很快，mruby 要是能赶上潮流就非常有前途&lt;/p&gt;</description>
      <author>qhwa</author>
      <pubDate>Fri, 28 Feb 2014 10:08:40 +0800</pubDate>
      <link>https://ruby-china.org/topics/17556</link>
      <guid>https://ruby-china.org/topics/17556</guid>
    </item>
    <item>
      <title>淘宝威客站点的部署</title>
      <description>&lt;p&gt;之前做&lt;a href="http://weike.taobao.com" rel="nofollow" target="_blank" title=""&gt;淘宝威客&lt;/a&gt;的时候，做了一个子项目 weike-deployment，用来快速部署一台新机器，可以把刚装完系统的 Linux 服务器，很快地变成一个生产环境的节点。&lt;/p&gt;

&lt;p&gt;实践下来，感受到了一些好处：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;添加新机器比较容易&lt;/li&gt;
&lt;li&gt;服务器的软件配置也加入了版本控制&lt;/li&gt;
&lt;li&gt;一些安装比较麻烦的软件（例如 imagemagick），不需要每次都去对着教程装了&lt;/li&gt;
&lt;li&gt;整个拓扑结构都有了文档，如果新人加入也可以很快上手（虽然一直没有新人……）&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;这个项目的目录结构：&lt;/p&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;weike&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;deployment&lt;/span&gt;
&lt;span class="o"&gt;|~&lt;/span&gt;&lt;span class="nx"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;                                  &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;一些shell脚本&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|-&lt;/span&gt;&lt;span class="nx"&gt;build_weike_server&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;&lt;span class="nx"&gt;restart_haproxy&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="s2"&gt;`-restart_nginx*
|~doc/                                  #=&amp;gt; 文档
| |-install-server.md
| `&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;readme&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;md&lt;/span&gt;
&lt;span class="o"&gt;|~&lt;/span&gt;&lt;span class="nx"&gt;etc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;                                  &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;软件配置&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|~&lt;/span&gt;&lt;span class="nx"&gt;ssh&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; &lt;span class="o"&gt;|-&lt;/span&gt;&lt;span class="nx"&gt;authorized_keys&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;&lt;span class="nx"&gt;config&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;&lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ssh&lt;/span&gt; &lt;span class="nx"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|-&lt;/span&gt;&lt;span class="nx"&gt;haproxy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cfg&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|-&lt;/span&gt;&lt;span class="nx"&gt;ldpath&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;conf&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|-&lt;/span&gt;&lt;span class="nx"&gt;nginx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;conf&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="s2"&gt;`-nginx.weike.conf
`&lt;/span&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;                                  &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;软件包&lt;/span&gt;&lt;span class="err"&gt;，&lt;/span&gt;&lt;span class="nx"&gt;预先下载好&lt;/span&gt;
  &lt;span class="o"&gt;|~&lt;/span&gt;&lt;span class="nx"&gt;rvm&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="s2"&gt;`~archives/
  |   `&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;ruby&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;1.9&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;p385&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bz2&lt;/span&gt;
  &lt;span class="o"&gt;|-&lt;/span&gt;&lt;span class="nx"&gt;ImageMagick&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;6.8&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bz2&lt;/span&gt;
  &lt;span class="o"&gt;|-&lt;/span&gt;&lt;span class="nx"&gt;jasper&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;1.900&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;gz&lt;/span&gt;
  &lt;span class="o"&gt;|-&lt;/span&gt;&lt;span class="nx"&gt;libmcrypt&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;2.5&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bz2&lt;/span&gt;
  &lt;span class="s2"&gt;`-node-v0.8.20.tar.gz
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;其中最核心的是安装脚本， &lt;code&gt;cmd/build_weike_server&lt;/code&gt;&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="c"&gt;#****************************************************************#&lt;/span&gt;
&lt;span class="c"&gt;# ScriptName: build-weike-server.sh&lt;/span&gt;
&lt;span class="c"&gt;# Author: hua.qiuh&lt;/span&gt;
&lt;span class="c"&gt;# Create Date: 2013-02-21&lt;/span&gt;
&lt;span class="c"&gt;# Modify Author: &lt;/span&gt;
&lt;span class="c"&gt;# Modify Date: 2013-02-21&lt;/span&gt;
&lt;span class="c"&gt;# Function: &lt;/span&gt;
&lt;span class="c"&gt;#***************************************************************#&lt;/span&gt;
&lt;span class="nv"&gt;BASE_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/home/www
&lt;span class="nv"&gt;SOURCE_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$BASE_DIR&lt;/span&gt;/src
&lt;span class="nv"&gt;CONFIG_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$BASE_DIR&lt;/span&gt;/etc
&lt;span class="nv"&gt;RUNNER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ads

&lt;span class="nv"&gt;current_user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="nb"&gt;whoami&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;

&lt;span class="k"&gt;function &lt;/span&gt;build_weike_server&lt;span class="o"&gt;(){&lt;/span&gt;

    init_base

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$current_user&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$RUNNER&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;then
        &lt;/span&gt;install_global_softwares
    &lt;span class="k"&gt;else
        &lt;/span&gt;install_project_softwares
    &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;function &lt;/span&gt;init_base&lt;span class="o"&gt;(){&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nv"&gt;$BASE_DIR&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;then
        &lt;/span&gt;&lt;span class="nb"&gt;sudo mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="nv"&gt;$BASE_DIR&lt;/span&gt;
        &lt;span class="nb"&gt;sudo chown&lt;/span&gt; &lt;span class="nv"&gt;$current_user&lt;/span&gt;:users &lt;span class="nv"&gt;$BASE_DIR&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt;
        &lt;span class="nb"&gt;cp&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nv"&gt;$BASE_DIR&lt;/span&gt;/
        &lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="nv"&gt;$BASE_DIR&lt;/span&gt;
        cmd/build_weike_server
        &lt;span class="nb"&gt;exit
    &lt;/span&gt;&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;function &lt;/span&gt;install_global_softwares&lt;span class="o"&gt;(){&lt;/span&gt;
    prepare_libs

    install_git
    install_nodejs
    install_imagemagick
    install_mcrypt

    install_nginx   &lt;span class="c"&gt;# web服务器上需要安装&lt;/span&gt;
    install_haproxy &lt;span class="c"&gt;# web服务器上需要安装&lt;/span&gt;

    add_local_lib_path
    install_sendmail_server
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;function &lt;/span&gt;prepare_libs&lt;span class="o"&gt;(){&lt;/span&gt;
    &lt;span class="nb"&gt;sudo &lt;/span&gt;yum &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
        gcc gcc-c++ autoconf libjpeg-devel libpng-devel &lt;span class="se"&gt;\&lt;/span&gt;
        freetype freetype-devel libxml2-devel zlib-devel &lt;span class="se"&gt;\&lt;/span&gt;
        glibc-devel glib2-devel bzip2-devel &lt;span class="se"&gt;\&lt;/span&gt;
        ncurses-devel curl-devel e2fsprogs-devel &lt;span class="se"&gt;\&lt;/span&gt;
        krb5-devel libidn-devel &lt;span class="se"&gt;\&lt;/span&gt;
        openldap-devel openldap-clients openldap-servers &lt;span class="se"&gt;\&lt;/span&gt;
        libmcrypt-devel libxslt-devel libtiff-devel &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"requirements installing failed!"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;exit&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;function &lt;/span&gt;login_as_runner&lt;span class="o"&gt;(){&lt;/span&gt;
    log &lt;span class="s1"&gt;'login as user: ads'&lt;/span&gt;
    &lt;span class="nb"&gt;sudo &lt;/span&gt;su ads
    &lt;span class="nb"&gt;cd&lt;/span&gt; ~
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;function &lt;/span&gt;&lt;span class="nb"&gt;logout&lt;/span&gt;&lt;span class="o"&gt;(){&lt;/span&gt;
    log &lt;span class="s1"&gt;'logout'&lt;/span&gt;
    &lt;span class="nb"&gt;exit&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;function &lt;/span&gt;install_git&lt;span class="o"&gt;(){&lt;/span&gt;
    info &lt;span class="s1"&gt;'&amp;gt;&amp;gt; Installing git'&lt;/span&gt;
    git &lt;span class="nt"&gt;--version&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; celebrate &lt;span class="s1"&gt;'git has been installed'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;return

    &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;yum &lt;span class="nb"&gt;install &lt;/span&gt;git
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;function &lt;/span&gt;install_nginx&lt;span class="o"&gt;(){&lt;/span&gt;
    info &lt;span class="s1"&gt;'&amp;gt;&amp;gt; Installing Nginx'&lt;/span&gt;
    &lt;span class="nv"&gt;weike_conf&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/home/tops/conf/vhosts/weike.taobao.com.conf
    &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="nv"&gt;$weike_conf&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; celebrate &lt;span class="s1"&gt;'Nginx has been installed'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;return

    &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;yum &lt;span class="nb"&gt;install &lt;/span&gt;tops-nginx &lt;span class="nt"&gt;-y&lt;/span&gt; 
    &lt;span class="nb"&gt;sudo mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /home/tops/conf/vhosts
    &lt;span class="nb"&gt;sudo cp&lt;/span&gt; &lt;span class="nv"&gt;$BASE_DIR&lt;/span&gt;/etc/nginx.conf /home/tops/conf/
    &lt;span class="nb"&gt;sudo ln&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nv"&gt;$BASE_DIR&lt;/span&gt;/etc/nginx.weike.conf &lt;span class="nv"&gt;$weike_conf&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;function &lt;/span&gt;install_haproxy&lt;span class="o"&gt;(){&lt;/span&gt;
    info &lt;span class="s1"&gt;'&amp;gt;&amp;gt; Installing HAProxy'&lt;/span&gt;
    &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; /etc/haproxy.cfg &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; celebrate &lt;span class="s1"&gt;'HAProxy has been installed'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;return

    &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;yum &lt;span class="nb"&gt;install &lt;/span&gt;haproxy &lt;span class="nt"&gt;-y&lt;/span&gt;
    &lt;span class="nb"&gt;sudo mv&lt;/span&gt; /etc/haproxy.cfg /etc/haproxy.cfg.origin
    &lt;span class="nb"&gt;sudo ln&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nv"&gt;$BASE_DIR&lt;/span&gt;/etc/haproxy.cfg /etc/haproxy.cfg
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;function &lt;/span&gt;add_local_lib_path&lt;span class="o"&gt;(){&lt;/span&gt;
    info &lt;span class="s1"&gt;'&amp;gt;&amp;gt; Adding /usr/local/lib to global library path'&lt;/span&gt;
    &lt;span class="nv"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/etc/ld.so.conf.d/local_lib.conf
    &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="nv"&gt;$target&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; celebrate &lt;span class="s1"&gt;'already added'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;return

    &lt;/span&gt;&lt;span class="nb"&gt;sudo cp&lt;/span&gt; &lt;span class="nv"&gt;$BASE_DIR&lt;/span&gt;/etc/ldpath.lib.conf /etc/ld.so.conf.d/local_lib.conf
    &lt;span class="nb"&gt;sudo &lt;/span&gt;ldconfig
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;function &lt;/span&gt;install_sendmail_server&lt;span class="o"&gt;(){&lt;/span&gt;
    info &lt;span class="s1"&gt;'&amp;gt;&amp;gt; Installing sendmail'&lt;/span&gt;
    &lt;span class="nb"&gt;sudo &lt;/span&gt;yum &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; sendmail &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/null
    &lt;span class="nb"&gt;sudo&lt;/span&gt; /etc/init.d/sendmail start
    &lt;span class="nb"&gt;sudo &lt;/span&gt;chkconfig sendmail on
    celebrate &lt;span class="s1"&gt;'sendmail has started'&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;function &lt;/span&gt;install_imagemagick&lt;span class="o"&gt;(){&lt;/span&gt;
    info &lt;span class="s1"&gt;'&amp;gt;&amp;gt; Installing ImageMagick'&lt;/span&gt;
    convert &lt;span class="nt"&gt;--version&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; celebrate &lt;span class="s1"&gt;'imagemagick has been installed'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;return

    &lt;/span&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;CFLAGS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"-O2 -fPIC"&lt;/span&gt;
    &lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;CXXFLAGS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$CFLAGS&lt;/span&gt;
    install_from_source &lt;span class="s1"&gt;'jasper'&lt;/span&gt;
    install_from_source &lt;span class="s1"&gt;'ImageMagick'&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;function &lt;/span&gt;install_mcrypt&lt;span class="o"&gt;(){&lt;/span&gt;
    info &lt;span class="s1"&gt;'&amp;gt;&amp;gt; Installing libmcrypt'&lt;/span&gt;
    &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; /usr/local/lib/libmcrypt.so &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; celebrate &lt;span class="s1"&gt;'libmcrypt has been installed'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;return

    &lt;/span&gt;install_from_source &lt;span class="s1"&gt;'libmcrypt'&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;function &lt;/span&gt;install_nodejs&lt;span class="o"&gt;(){&lt;/span&gt;
    info &lt;span class="s1"&gt;'&amp;gt;&amp;gt; Installing Nodejs'&lt;/span&gt;
    node &lt;span class="nt"&gt;--version&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; celebrate &lt;span class="s1"&gt;'Nodejs has been installed'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;return

    &lt;/span&gt;install_from_source &lt;span class="s1"&gt;'node'&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;function &lt;/span&gt;install_project_softwares&lt;span class="o"&gt;(){&lt;/span&gt;
    install_rvm
    install_ruby
    install_weike_components
    config_ssh_gitlab

    celebrate &lt;span class="s1"&gt;'done!'&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;function &lt;/span&gt;install_rvm&lt;span class="o"&gt;(){&lt;/span&gt;
    info &lt;span class="s1"&gt;'&amp;gt;&amp;gt; Installing rvm'&lt;/span&gt;
    rvm &lt;span class="nt"&gt;--version&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; celebrate &lt;span class="s1"&gt;'rvm has been installed'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;

    &lt;span class="se"&gt;\c&lt;/span&gt;url &lt;span class="nt"&gt;-L&lt;/span&gt; https://get.rvm.io | bash &lt;span class="nt"&gt;-s&lt;/span&gt; stable
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'[[ -s "$HOME/.rvm/scripts/rvm" ]] &amp;amp;&amp;amp; . "$HOME/.rvm/scripts/rvm"'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.bashrc
    &lt;span class="nb"&gt;source&lt;/span&gt; ~/.bashrc

    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'install: --no-rdoc --no-ri'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.gemrc
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'update:  --no-rdoc --no-ri'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.gemrc
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;function &lt;/span&gt;install_ruby&lt;span class="o"&gt;(){&lt;/span&gt;
    info &lt;span class="s1"&gt;'&amp;gt;&amp;gt; Installing ruby'&lt;/span&gt;
    ruby &lt;span class="nt"&gt;--version&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; celebrate &lt;span class="s1"&gt;'Ruby has been installed'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;return

    &lt;/span&gt;&lt;span class="nb"&gt;cp&lt;/span&gt; &lt;span class="nv"&gt;$BASE_DIR&lt;/span&gt;/src/rvm/archives/&lt;span class="k"&gt;*&lt;/span&gt; ~/.rvm/archives/
    rvm &lt;span class="nb"&gt;install &lt;/span&gt;1.9.3 &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; rvm use 1.9.3 &lt;span class="nt"&gt;--default&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;function &lt;/span&gt;install_weike_components&lt;span class="o"&gt;(){&lt;/span&gt;
    install_bundler
    install_rmagick
    install_rubymcrypt
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;function &lt;/span&gt;install_bundler&lt;span class="o"&gt;(){&lt;/span&gt;
    info &lt;span class="s1"&gt;'&amp;gt;&amp;gt; Installing bundler'&lt;/span&gt;
    bundle &lt;span class="nt"&gt;--version&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; celebrate &lt;span class="s1"&gt;'bundler has been installed'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;return

    &lt;/span&gt;gem &lt;span class="nb"&gt;install &lt;/span&gt;bundler
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;function &lt;/span&gt;install_rmagick&lt;span class="o"&gt;(){&lt;/span&gt;
    info &lt;span class="s1"&gt;'&amp;gt;&amp;gt; Installing rmagick'&lt;/span&gt;
    &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;gem list &lt;span class="nt"&gt;-i&lt;/span&gt; rmagick&lt;span class="sb"&gt;`&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"true"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; celebrate &lt;span class="s1"&gt;'rmagick has been installed'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;return

    &lt;/span&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PKG_CONFIG_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/usr/local/lib/pkgconfig:&lt;/span&gt;&lt;span class="nv"&gt;$PKG_CONFIG_PATH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    gem &lt;span class="nb"&gt;install &lt;/span&gt;rmagick
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;function &lt;/span&gt;install_rubymcrypt&lt;span class="o"&gt;(){&lt;/span&gt;
    info &lt;span class="s1"&gt;'&amp;gt;&amp;gt; Installing ruby-mcrypt'&lt;/span&gt;
    &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;gem list &lt;span class="nt"&gt;-i&lt;/span&gt; ruby-mcrypt&lt;span class="sb"&gt;`&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"true"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; celebrate &lt;span class="s1"&gt;'ruby-mcrypt has been installed'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;return

    &lt;/span&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PKG_CONFIG_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/usr/local/lib/pkgconfig:&lt;/span&gt;&lt;span class="nv"&gt;$PKG_CONFIG_PATH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    gem &lt;span class="nb"&gt;install &lt;/span&gt;ruby-mcrypt &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nt"&gt;--with-mcrypt-dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/usr/local
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;function &lt;/span&gt;config_ssh_gitlab&lt;span class="o"&gt;(){&lt;/span&gt;
    &lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; ~/.ssh
    &lt;span class="nb"&gt;cp&lt;/span&gt; &lt;span class="nv"&gt;$BASE_DIR&lt;/span&gt;/etc/ssh/&lt;span class="k"&gt;*&lt;/span&gt; ~/.ssh
    &lt;span class="nb"&gt;chown&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="nb"&gt;whoami&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt; ~/.ssh &lt;span class="nt"&gt;-R&lt;/span&gt;
    &lt;span class="nb"&gt;chmod &lt;/span&gt;600 ~/.ssh/&lt;span class="k"&gt;*&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;


&lt;span class="c"&gt;#--------------- helpers --------------&lt;/span&gt;

&lt;span class="k"&gt;function &lt;/span&gt;install_from_source&lt;span class="o"&gt;(){&lt;/span&gt;
    &lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="nv"&gt;$SOURCE_DIR&lt;/span&gt;
    extract &lt;span class="nv"&gt;$1&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;warn &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt; source not found!"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    log &lt;span class="s2"&gt;"Compiling &lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    make &lt;span class="nt"&gt;-s&lt;/span&gt; clean
    ./configure &lt;span class="nv"&gt;$2&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; make &lt;span class="nt"&gt;-j&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;make &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;return
    &lt;/span&gt;warn &lt;span class="s2"&gt;"installing &lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt; failed"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;function &lt;/span&gt;extract&lt;span class="o"&gt;(){&lt;/span&gt;
    &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;tar &lt;/span&gt;xzf &lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;.tar.gz &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;tar &lt;/span&gt;xzf &lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;.tgz &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;tar &lt;/span&gt;xjf &lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;.tar.bz2 &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;tar &lt;/span&gt;xjf &lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;.tar.bz &lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;function &lt;/span&gt;log&lt;span class="o"&gt;(){&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\e&lt;/span&gt;&lt;span class="s2"&gt;[35m&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="se"&gt;\e&lt;/span&gt;&lt;span class="s2"&gt;[0m"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;function &lt;/span&gt;warn&lt;span class="o"&gt;(){&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\e&lt;/span&gt;&lt;span class="s2"&gt;[31m&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="se"&gt;\e&lt;/span&gt;&lt;span class="s2"&gt;[0m"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;function &lt;/span&gt;info&lt;span class="o"&gt;(){&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$1&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;function &lt;/span&gt;celebrate&lt;span class="o"&gt;(){&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\e&lt;/span&gt;&lt;span class="s2"&gt;[32m&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="se"&gt;\e&lt;/span&gt;&lt;span class="s2"&gt;[0m"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

build_weike_server
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;可能对很多人来说不是新鲜的东西啦，其实只是受 Unix 的影响，认同这条原则：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;所有东西都是文件&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;后续想更加自动化，借鉴一下 Arch Linux 的方式。&lt;/p&gt;</description>
      <author>qhwa</author>
      <pubDate>Wed, 03 Jul 2013 21:55:01 +0800</pubDate>
      <link>https://ruby-china.org/topics/12222</link>
      <guid>https://ruby-china.org/topics/12222</guid>
    </item>
    <item>
      <title>Passenger 怎么做到无缝更新部署？</title>
      <description>&lt;p&gt;passenger 的重启很方便，&lt;code&gt;touch tmp/restart.txt&lt;/code&gt;
可是之后首次访问就会有很长的启动时间&lt;/p&gt;

&lt;p&gt;查了一下文档，只有企业版有&lt;a href="http://www.modrails.com/documentation/Users%20guide%20Nginx.html#PassengerRollingRestarts" rel="nofollow" target="_blank" title=""&gt;rolling restart&lt;/a&gt;功能……这是要让人抓狂么，难道每次更新都放到夜深人静的时候？&lt;/p&gt;

&lt;p&gt;大家有什么法子吗？
passenger_pool_idle_time 能解决吗？&lt;/p&gt;</description>
      <author>qhwa</author>
      <pubDate>Thu, 24 Jan 2013 14:17:31 +0800</pubDate>
      <link>https://ruby-china.org/topics/8322</link>
      <guid>https://ruby-china.org/topics/8322</guid>
    </item>
    <item>
      <title>Most active GitHub users in China</title>
      <description>&lt;p&gt;&lt;a href="https://github.com/lifesinger/lifesinger.github.com/blob/master/lab/2013/github-users/github-users-china.md" rel="nofollow" target="_blank"&gt;https://github.com/lifesinger/lifesinger.github.com/blob/master/lab/2013/github-users/github-users-china.md&lt;/a&gt;
按年度贡献次数排的，好玩的地方很多啊！&lt;/p&gt;</description>
      <author>qhwa</author>
      <pubDate>Fri, 11 Jan 2013 13:19:02 +0800</pubDate>
      <link>https://ruby-china.org/topics/7981</link>
      <guid>https://ruby-china.org/topics/7981</guid>
    </item>
    <item>
      <title>对 Flash Socket 的补充</title>
      <description>&lt;p&gt;RubyConf2012 大会上 &lt;a href="/yedingding" class="user-mention" title="@yedingding"&gt;&lt;i&gt;@&lt;/i&gt;yedingding&lt;/a&gt;  分享的 Ruby Realtime web 中提到的几种技术方案选择，XHR polling、HTTP Long Polling、HTTPStream、Flash Socket、Web Socket，其中关于 Flash Socket 的描述我觉得可以探讨一下，正好我的工作和 Ruby、Flash 都有很多接触。&lt;/p&gt;
&lt;h3 id="1. 误区： Flash Socket 需要 Flash Media Server 配合？"&gt;1. 误区：Flash Socket 需要 Flash Media Server 配合？&lt;/h3&gt;
&lt;p&gt;Socket 是一种简单、宽松的通信方式，HTTP 协议也是在 Socket 方式的基础上定了一些 request 和 response 的协议。Flash Socket 是在 Flash 应用程序中和服务器端建立一个 Socket 连接，至于后端是 Flash Media Server 还是开源的 Red5，或是 Ruby Socket Server，都是可以的。只要遵循 Socket 的规范，前后端的实现都是任意组合的。前端可以是 Flash，可以是 Silverlight，也可以是 Java Applet。后端的选择就更多了。&lt;/p&gt;
&lt;h3 id="2. 补充： Web Socket 在低级浏览器上的支持"&gt;2. 补充：Web Socket 在低级浏览器上的支持&lt;/h3&gt;
&lt;p&gt;低级浏览器（IE6、7、8）中可以利用 Flash Web Socket 做 JS Web Socket 方案的 fallback。Flash 支持最底层的 Socket，也可以很容易实现 Web Socket、XML Socket 这些封装。我们开发过 Web 版的阿里旺旺聊天界面，客户端就是使用了 Flash Web Socket 为主，JS Web Socket 为 fallback 的方案。然后封装了一个 Web Socket 组件，业务逻辑中不需要关心 Web Socket 是 JS 还是 Flash 实现。 &lt;/p&gt;

&lt;p&gt;虽然大家用 Flash Socket 的机会比较少，而且短期内 Flash Socket 必然被 JS web socket 或 Flash web socket 代替，个人认为以后 Flash 在桌面 web 上的机会会越来越少，但是目前 Flash 还是可以做一些 HTML5 的有益补充，所以我斗胆在 Ruby 社区抛个砖，说一下 Flash Socket 的东西，方便大家在技术选型的时候，当你的应用需要考虑低级浏览器的时候，当你的应用需要跨域 realtime 的时候，也可以考虑一下 Flash。&lt;/p&gt;</description>
      <author>qhwa</author>
      <pubDate>Mon, 19 Nov 2012 11:39:00 +0800</pubDate>
      <link>https://ruby-china.org/topics/6891</link>
      <guid>https://ruby-china.org/topics/6891</guid>
    </item>
    <item>
      <title>做了一个自动将字符转成 utf8 编码的 gem</title>
      <description>&lt;p&gt;&lt;a href="http://rubygems.org/gems/string_utf8" rel="nofollow" target="_blank"&gt;http://rubygems.org/gems/string_utf8&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="n"&gt;install&lt;/span&gt; &lt;span class="n"&gt;string_utf8&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;给 String 加了一个 utf8! 方法，会使用一系列的字符集去猜测，直到可以正确转成 utf8 为止。目前主要是自己用在中文的辨识上，自己用在很多项目里面，感觉还是很方便的。&lt;/p&gt;

&lt;p&gt;用法示例：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'string/utf8'&lt;/span&gt;
&lt;span class="nb"&gt;p&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;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'input.txt'&lt;/span&gt; &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;utf8!&lt;/span&gt;  &lt;span class="c1"&gt;#不用去关心原来是什么编码&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;</description>
      <author>qhwa</author>
      <pubDate>Mon, 13 Aug 2012 15:30:29 +0800</pubDate>
      <link>https://ruby-china.org/topics/4909</link>
      <guid>https://ruby-china.org/topics/4909</guid>
    </item>
    <item>
      <title>scaling github： github 背后的理念分享</title>
      <description>&lt;p&gt;很多值得学习的地方
&lt;a href="http://speakerdeck.com/u/holman/p/scaling-github" rel="nofollow" target="_blank"&gt;http://speakerdeck.com/u/holman/p/scaling-github&lt;/a&gt;  &lt;/p&gt;</description>
      <author>qhwa</author>
      <pubDate>Wed, 15 Feb 2012 13:23:00 +0800</pubDate>
      <link>https://ruby-china.org/topics/1209</link>
      <guid>https://ruby-china.org/topics/1209</guid>
    </item>
    <item>
      <title>用 ruby 做了一个 web 前端代码检查工具</title>
      <description>&lt;p&gt;名称叫做 fdlint，用来对 HTML/JS/CSS 代码进行扫描，找出一些不合理的地方。
做这个是因为我是前端开发工程师，团队 code review 的时候，发现有很多检查项目是可以用工具扫描的，于是就有了这个想法。&lt;/p&gt;

&lt;p&gt;因为喜欢 ruby，就用 ruby 做了。我的 ruby 属于刚刚入门，幸好有高手相助，核心部分是另外一位牛人同事 (bencode) 一起写的，细心的可以看看 bencode 和我的提交记录，明显熟练程度很不一样，呵呵。开发的过程中学到了很多很多，之后会不断完善功能、重构代码。&lt;/p&gt;

&lt;p&gt;项目主页：&lt;a href="https://github.com/qhwa/fdlint" rel="nofollow" target="_blank"&gt;https://github.com/qhwa/fdlint&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;请提些意见吧！不管是代码上还是功能上的。&lt;/p&gt;</description>
      <author>qhwa</author>
      <pubDate>Wed, 01 Feb 2012 22:41:45 +0800</pubDate>
      <link>https://ruby-china.org/topics/1002</link>
      <guid>https://ruby-china.org/topics/1002</guid>
    </item>
  </channel>
</rss>
