<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom">

  <title><![CDATA[hSATAC]]></title>
  
  <link href="http://blog.hsatac.net/" />
  <updated>2012-02-02T15:09:07+08:00</updated>
  <id>http://blog.hsatac.net/</id>
  <author>
    <name><![CDATA[hSATAC]]></name>
    
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/hsatac" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="hsatac" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry>
    <title type="html"><![CDATA[PHP-Resque Auto Scale Workers]]></title>
    <link href="http://blog.hsatac.net/2012/02/php-resque-auto-scale-workers/" />
    <updated>2012-02-02T14:56:00+08:00</updated>
    <id>http://blog.hsatac.net/2012/02/php-resque-auto-scale-workers</id>
    <content type="html"><![CDATA[<p><a href="https://github.com/chrisboulton/php-resque">PHP-Resque</a> is an amazing PHP port of <a href="http://github.com/defunkt/resque/">Resque</a>. After playing it for a while, an idea crossed my mind: It&#8217;s a total waste to create numbers of workers when there&#8217;s not many jobs to do. How about auto scale it? With the EventListener design of PHP-Resque, we could achieve it by writing some simple hooks.</p>

<p>Also, is solved <a href="https://github.com/chrisboulton/php-resque/issues/32">issue #32 of PHP-Resque</a>.</p>

<p>Here&#8217;s my code: <a href="https://github.com/hSATAC/php-resque-auto-scale">PHP-Resque Auto Scale</a></p>

<h2>Introduction</h2>

<p>This is a project trying to build an auto scale architecture of PHP-Resque.</p>

<!-- more -->


<h2>Design</h2>

<h3>Expected Behavior</h3>

<ul>
<li><p>Trigger <code>afterEnqueue</code> to check the total job number of this queue.</p></li>
<li><p>If the number larger than <code>15</code> than check the total number of workers involved in this queue.</p></li>
<li><p>If the worker number is not enough, create one or more workers.</p>

<ul>
<li><p>If there are more than one server, divided the number equally to each server.</p></li>
<li><p>In the mean time, try to create workers that deal the same queues on each server.</p></li>
</ul>
</li>
<li><p>Trigger <code>beforeFork</code> to check the total job number and worker number, close the useless ones.</p></li>
</ul>


<h3>Number of Jobs and Workers</h3>

<ul>
<li><p>1~15 jobs => 1 worker</p></li>
<li><p>16~25 jobs => 2 workers</p></li>
<li><p>26~40 jobs => 3 workers</p></li>
<li><p>41~60 jobs => 4 workers</p></li>
<li><p>60+ jobs => 5 workers</p></li>
</ul>


<h2>Usage</h2>

<ul>
<li>You need to add the queue type as a member static variable to your Job class. Like this:</li>
</ul>


<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="cp">&lt;?php</span>
</span><span class='line'><span class="k">class</span> <span class="nc">PHP_Job</span>
</span><span class='line'><span class="p">{</span>
</span><span class='line'>    <span class="k">static</span> <span class="k">public</span> <span class="nv">$queue</span> <span class="o">=</span> <span class="s2">&quot;default&quot;</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'><span class="cp">?&gt;</span><span class="x"></span>
</span></code></pre></td></tr></table></div></figure>


<ul>
<li><p>Require <code>plugin.php</code> both in your resque init script and enqueue part.</p></li>
<li><p>Change the setting and code in <code>plugin.php</code> based on your need.</p></li>
<li><p>Start only one worker via your resque init script.</p></li>
<li><p>Now it&#8217;s auto-scalable.</p></li>
</ul>


<h2>Disclaimer</h2>

<p>For now it&#8217;s all experimental design.</p>

<p>All numbers and codes are not from production enviroments nor runned benchmarks. It&#8217;s just a prototype for now, but it does what it says.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Youtube 加入我的最愛後自動抓檔上傳至 Google Music]]></title>
    <link href="http://blog.hsatac.net/2012/01/youtube-favorite-add-google-music/" />
    <updated>2012-01-17T19:33:00+08:00</updated>
    <id>http://blog.hsatac.net/2012/01/youtube-favorite-add-google-music</id>
    <content type="html"><![CDATA[<p>這個標題很冗長，不過正是 Youtube 加入我的最愛後自動抓檔上傳到 Google Music 。</p>

<p>這個需求是這樣來的，我常常在 Youtube 聽到喜歡的歌，習慣性按加入最愛，隨時可以拿出來重複播放。不過在最近都用 Google Music 來管理我的音樂庫，行進時也可以用 Android 上的 Google Music App 聆聽音樂。</p>

<p>但這樣一來，就要透過 Youtube Downloader 等網站或軟體抓下影片檔後再轉檔、上傳到 Google Music ，這樣實在是太麻煩了。</p>

<p>有沒有什麼方法可以把這個過程自動化呢？第一個想到的是利用 ifttt 。不過 ifttt 要達成這個功能需要繞許多彎路，最後決定自己寫一個。</p>

<!--more-->


<p>想法很簡單，大概分為四部分：</p>

<ul>
<li><p>讀取 Youtube 我的最愛</p></li>
<li><p>抓到有新增就取得資訊下載影片</p></li>
<li><p>透過 <code>ffmpeg</code> 之類轉為 mp3</p></li>
<li><p>透過 Google Music Manager 上傳</p></li>
</ul>


<p>做了一番 survey 後發現 <a href="https://github.com/rg3/youtube-dl">youtube-dl</a> 這個工具實在非常好用。他是用 python 寫的一個 script ，只要丟網址給他就會幫你下載。更棒的是他連 <code>ffmpeg</code> 都接好了，加上參數就可以直接輸出成 mp3 檔案。</p>

<p>抓取的指令是：</p>

<p><code>youtube-dl -o "%(title)s.%(ext)s" -q --extract-audio --audio-format "mp3" "[youtube_url]"</code></p>

<p>剩下的工作就只剩下讀取 Youtube 我的最愛，判斷加入的時間。想來應該很簡單，不過這部份卻卡了一兩個小時。</p>

<p>原因是 <strong>Youtube 的 API 寫的太不清楚啦！！！</strong></p>

<p>根據 <a href="http://code.google.com/intl/zh-TW/apis/youtube/2.0/developers_guide_protocol_favorites.html#Retrieving_favorite_videos">GData Youtube API</a> ：</p>

<blockquote><p>The <code>&lt;published&gt;</code> tag in a favorite videos feed entry identifies the time that the video was marked as a favorite and not the time that the video was published.</p></blockquote>

<p>用 <code>&lt;published&gt;</code> 這個欄位就可以取得這筆影片新增到我的最愛的時間，這樣就可以用來判斷是否是新加入的項目。</p>

<p>但是他從頭到尾沒有提到 <strong>這個 API 要用 v=2 來連這個欄位才會有效</strong> 這件事。如果沒有指定 version ，這個欄位出來的值是影片上傳時間，卡在這邊超久的啊。</p>

<p>總之用一個檔案來記錄上次抓取的時間，就可以達成原本的目的了。</p>

<p>記得最後把 Google Music Manager 設定成這個目錄，這樣轉好的 mp3 就會自動上傳到 Google Music 啦。</p>

<p>所有的程式碼在這裡。</p>

<p><a href="https://github.com/hSATAC/youtube-favorite-to-google-music">https://github.com/hSATAC/youtube-favorite-to-google-music</a></p>

<h3>附錄</h3>

<p>其實原本的需求是抓下來以後先存進 itunes 再上傳到 Google Music ，但是後來因為現在沒在用 itunes 所以簡化了。</p>

<p>如果有這個需求的朋友可以參考 <a href="http://dougscripts.com/itunes/itinfo/folderaction01.php">Folder Actions and iTunes</a> (Mac Only)。</p>

<p>對指定資料夾設定動作，當有新增音樂檔案到此資料夾的時候自動把檔案丟進 itunes 。再把 Google Music Manager 設定成自動上傳 itunes 新增的音樂即可。</p>

<p>之後可能會加上轉好 mp3 後加上 ID3 TAG 的功能吧，不過那又是另外一個故事了(遠目)。</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Redmine migration from Trac 0.12]]></title>
    <link href="http://blog.hsatac.net/2012/01/redmine-migrate-from-trac-0-dot-12/" />
    <updated>2012-01-13T14:03:00+08:00</updated>
    <id>http://blog.hsatac.net/2012/01/redmine-migrate-from-trac-0-dot-12</id>
    <content type="html"><![CDATA[<p>This article will demostrate a near perfect redmine migration from trac 0.12 step by step.</p>

<ul>
<li><a href="http://www.redmine.org/projects/redmine/wiki/HowTo_install_Redmine_on_CentOS_5">Install Redmine on CentOS 5</a>

<ul>
<li>Install Ruby</li>
<li>Install rubygem</li>
<li>Install passenger

<ul>
<li>/etc/conf.d/ruby.conf</li>
</ul>
</li>
</ul>
</li>
</ul>


<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>LoadModule passenger_module /usr/lib/ruby/gems/1.8/gems/passenger-3.0.11/ext/apache2/mod_passenger.so
</span><span class='line'>PassengerRoot /usr/lib/ruby/gems/1.8/gems/passenger-3.0.11
</span><span class='line'>PassengerRuby /usr/bin/ruby</span></code></pre></td></tr></table></div></figure>


<pre><code>* /etc/httpd/conf.d/redmine.conf
</code></pre>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>   &lt;VirtualHost *:80&gt;
</span><span class='line'>      ServerName redmine.miiicasa.com 
</span><span class='line'>      DocumentRoot /home/m/share/htdocs/redmine/public
</span><span class='line'>      &lt;Directory /home/m/share/htdocs/redmine/public&gt;
</span><span class='line'>         AllowOverride all    
</span><span class='line'>         Options -MultiViews    
</span><span class='line'>      &lt;/Directory&gt;
</span><span class='line'>   &lt;/VirtualHost&gt;</span></code></pre></td></tr></table></div></figure>


<!--more-->


<ul>
<li>Get Redmine source from <a href="https://github.com/miiicasa/redmine">miiiCasa github repo</a> (bundler integrated and migrate_from_trac.rake modified)</li>
<li>install bundler and bundle install</li>
</ul>


<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>sudo gem install bundler
</span><span class='line'>bundle install</span></code></pre></td></tr></table></div></figure>


<ul>
<li>Setup mysql database and user</li>
</ul>


<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>create database redmine character set utf8;
</span><span class='line'>create user 'redmine'@'localhost' identified by 'my_password';
</span><span class='line'>grant all privileges on redmine.* to 'redmine'@'localhost';</span></code></pre></td></tr></table></div></figure>


<ul>
<li>cp config/database.yml.example config/database.yml and modify it based on previous settings.</li>
<li>cp config/configure.yml.example config/configure.yml and modify it.</li>
<li>Generate the session store</li>
</ul>


<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>RAILS_ENV=production bundle exec rake generate_session_store</span></code></pre></td></tr></table></div></figure>


<ul>
<li>Migrate the database models</li>
</ul>


<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>RAILS_ENV=production bundle exec rake db:migrate</span></code></pre></td></tr></table></div></figure>


<ul>
<li>Load default data</li>
</ul>


<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>RAILS_ENV=production bundle exec rake redmine:load_default_data</span></code></pre></td></tr></table></div></figure>


<ul>
<li>Migrate from trac

<ul>
<li>install sqlite3-ruby</li>
</ul>
</li>
</ul>


<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>sudo gem install sqlite3-ruby</span></code></pre></td></tr></table></div></figure>


<ul>
<li>migrate from trac</li>
</ul>


<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>RAILS_ENV=production bundle exec rake redmine:migrate_from_trac
</span><span class='line'>...
</span><span class='line'>Are you sure you want to continue ? [y/N] y                     
</span><span class='line'>
</span><span class='line'>Trac directory []: /var/www/trac/miiicasa
</span><span class='line'>Trac database adapter (sqlite, sqlite3, mysql, postgresql) [sqlite3]:
</span><span class='line'>Trac database encoding [UTF-8]: 
</span><span class='line'>Target project identifier []: miiicasa</span></code></pre></td></tr></table></div></figure>


<ul>
<li><p>git clone https://github.com/xfalcons/migrate-trac-to-redmine.git
Follow the instruction.</p></li>
<li><p>Setup Redmine</p>

<ul>
<li>Make all users admin:</li>
</ul>
</li>
</ul>


<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>$ RAILS_ENV=production ./script/console
</span><span class='line'>..
</span><span class='line'>for u in User.all
</span><span class='line'>  u.admin = true
</span><span class='line'>  u.save
</span><span class='line'>end</span></code></pre></td></tr></table></div></figure>


<ul>
<li>Login and setup scm path</li>
<li>Load git repo from script (prevent timeout)</li>
</ul>


<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>$ ruby script/runner "Repository.fetch_changesets" -e production</span></code></pre></td></tr></table></div></figure>


<p>  This action could take a very long time (maybe 1 day) and it got no progress bar nor any output. If you want to check where it went, try:</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>ps axww | grep git | grep -v grep</span></code></pre></td></tr></table></div></figure>


<p>  You&#8217;ll see it&#8217;s parsing git log.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[PHP-Resque 簡介]]></title>
    <link href="http://blog.hsatac.net/2012/01/php-resque-introduction/" />
    <updated>2012-01-06T15:14:00+08:00</updated>
    <id>http://blog.hsatac.net/2012/01/php-resque-introduction</id>
    <content type="html"><![CDATA[<p><a href="https://github.com/defunkt/resque">Resque</a> 是 Github 基於 Redis 開發的 background job 系統。相較其他肥大的 queue 系統， Resque 的設計真的非常單純簡潔，充分利用 Redis 的特性。更多介紹可以看<a href="https://github.com/blog/542-introducing-resque">原作者的 Blog</a></p>

<p><a href="https://github.com/chrisboulton/php-resque">PHP-Resque</a> 是把 Resque porting 到 PHP 的專案。使用和 原本 Resque 一樣的概念和設計。甚至連 Redis 的 key 命名都一樣，因此也可以使用 Ruby 版本的 <a href="https://github.com/defunkt/resque-web">resque-web</a> 來監控 PHP-Resque 的運行狀況。</p>

<h2>設計</h2>

<p>Resque 的設計有兩個角色： Job 和 Worker。 每個 Job 都是定義成類別，新增 Job 的時候會將 Job 的類別和相關參數 json_encode 後儲存到不同的 queue 裡面，而 Worker(s) 則會依序從 redis 讀取 Job 出來執行。</p>

<p>執行的時候並不是這個 Worker 本身去執行，而是會 fork 一個 process 來執行。這樣設計是為了避免時間一長， Worker 的記憶體管理不良導致卡死的狀況。</p>

<p>讀取 queue 時會依據你啟動 worker 的時候給的 queue 順序來讀取，因此優先權較高的 queue 要設定在前面。 Redis 可以是單機或 RedisCluster。而許多不同伺服器上可以按需求部屬執行不同 queue 的 worker。</p>

<p>Resque Job 執行失敗並不會自動重試，而是把它丟到 fail 的 queue 裡面。如果你有重試的需求可能要自己處理。若是有特別重要的 Job 需要監控執行狀態的，可以參考 README 中的 Tracking Job Statuses 一節。</p>

<p>以下先來介紹如何使用 PHP-Resque：</p>

<h2>安裝 PHP-Resque</h2>

<p>安裝非常容易，只要 <code>git clone https://github.com/chrisboulton/php-resque.git</code> 下來，放到你想要的地方，由於 Resque 沒有 config 檔的設計，設定都是寫在環境變數中再執行就可以了。</p>

<!-- more -->


<h2>環境變數</h2>

<p>PHP-Resque 支援的環境變數有：</p>

<ul>
<li><p>QUEUE - 這個是必要的，會決定 worker 要執行什麼任務，重要的在前，例如 <code>QUEUE=notify,mail,log</code> 。也可以設定為 <code>QUEUE=*</code> 表示執行所有任務。</p></li>
<li><p>APP_INCLUDE - 這也可以說是必要的，因為 Resque 的 Job 都是寫成物件，那 worker 執行的時候當然要把物件的檔案引入進來。可以設成 <code>APP_INCLUDE=require.php</code> 再在 require.php 中引入所有 Job 的 Class 檔案即可。</p></li>
<li><p>COUNT - 設定 worker 數量，預設是1 <code>COUNT=5</code> 。</p></li>
<li><p>REDIS_BACKEND - 設定 Redis 的 ip, port。如果沒設定，預設是連 <code>localhost:6379</code> 。</p></li>
<li><p>LOGGING, VERBOSE - 設定 log， <code>VERBOSE=1</code> 即可。</p></li>
<li><p>VVERBOSE - 比較詳細的 log， <code>VVERBOSE=1</code> debug 的時候可以開出來看。</p></li>
<li><p>INTERVAL - worker 檢查 queue 的間隔，預設是五秒 <code>INTERVAL=5</code> 。</p></li>
<li><p>PIDFILE - 如果你是開單 worker，可以指定 PIDFILE 把 pid 寫入，例如 <code>PIDFILE=/var/run/resque.pid</code> 。</p></li>
</ul>


<p>有一個 Resque 支援，但 PHP-Resque 沒有的參數叫 <code>BACKGROUND</code> 可以把 resque 丟到背景執行。不過這個其實不太重要，有需要的話自己加個 <code>php resque.php &amp;</code> 就可以了。</p>

<p>所以，你的指令最後可能會變這樣：</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>QUEUE=* APP_INCLUDE=require.php COUNT=5 VVERBOSE=1 php resque.php</span></code></pre></td></tr></table></div></figure>


<p>如果覺得太長，可以寫一支啟動 script 來輔助你，我有寫一支可供參考：</p>

<div><script src='https://gist.github.com/1619972.js?file='></script>
<noscript><pre><code>#!/bin/bash
export APP_INCLUDE=resque/require.php
export QUEUE=*
export COUNT=1
export VVERBOSE=1 # for debugging
export REDIS_BACKEND=localhost:6379
. /etc/rc.d/init.d/functions

start() {
    /usr/bin/php ../lib/sdk/php-resque/resque.php
}

stop() {
    ps -ef | grep resque | grep -v grep | grep -v resque-web | awk '{print $2}' | xargs kill -15
}
kill() {
    ps -ef | grep resque | grep -v grep | grep -v resque-web | awk '{print $2}' | xargs kill -9
}
case &quot;$1&quot; in
    start)
         number=$(ps aux | grep php-resque/resque.php | grep -v grep | wc -l)
        if [ $number -gt 0 ]
        then
          echo &quot;php-resque is running. ($number workers)&quot;
          echo &quot;You may wanna stop them before you start.&quot;
          start
        else
          start
        fi
    ;;

    stop)
        stop
    ;;

    kill)
        kill
    ;;

    status)
        number=$(ps aux | grep php-resque/resque.php | grep -v grep | wc -l)
        if [ $number -gt 0 ]
        then
          echo &quot;php-resque is running. ($number workers)&quot;
        else
          echo &quot;php-resque is not running.&quot;
        fi
    ;;

    *)
        echo -n &quot;Usage: $0 {start|stop|status}&quot;
esac
</code></pre></noscript></div>


<h2>使用 PHP-Resque</h2>

<p>把檔案抓下來以後一定想先試驗看看的，確定你的 redis-server 都有正常啟動後，在 demo 資料夾下面有幾個檔案可以先試驗看看。</p>

<p>切到 demo 目錄後，執行 <code>VVERBOSE=1 QUEUE=* php resque.php</code> 應該會看到 resque 已經開始執行了。</p>

<p>執行 <code>php queue.php PHP_Job</code> 、 <code>php queue.php Bad_PHP_Job</code> 、 <code>php queue.php Long_PHP_Job</code> 、 <code>php queue.php PHP_Error_Job</code> 可以把工作丟進 queue 裡面，看看執行的結果。</p>

<p>後面帶的名稱其實就是 Job class 的名稱，所以 PHP-Resque 在執行時也要把相關的 class 檔案設定在 APP_INCLUDE 引入才行。</p>

<p>Job 的 class 很簡單，大概長這樣：</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="cp">&lt;?php</span>
</span><span class='line'><span class="k">class</span> <span class="nc">My_Job</span>
</span><span class='line'><span class="p">{</span>
</span><span class='line'>    <span class="k">public</span> <span class="k">function</span> <span class="nf">perform</span><span class="p">()</span>
</span><span class='line'>    <span class="p">{</span>
</span><span class='line'>        <span class="c1">// Work work work</span>
</span><span class='line'>        <span class="k">echo</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">args</span><span class="p">[</span><span class="s1">&#39;name&#39;</span><span class="p">];</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'><span class="cp">?&gt;</span><span class="x"></span>
</span></code></pre></td></tr></table></div></figure>


<p>只要定義 perform 方法， Worker 就會把 Job new 出來以後執行 perform 。</p>

<p>當然，也可以定義 <code>setUp()</code> 和 <code>tearDown()</code> 方法，前者會在 <code>perform()</code> 執行前執行，後者會在 <code>perform()</code> 執行後執行。</p>

<p>需要注意的是，Job exit 後都視為正常執行，如果要讓他判斷失敗丟到 fail queue 中的話，需要 throw exception。</p>

<p>將 Job 塞入 queue 的方式是：</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="cp">&lt;?php</span>
</span><span class='line'><span class="k">require_once</span> <span class="s1">&#39;lib/Resque.php&#39;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="nx">Resque</span><span class="o">::</span><span class="na">setBackend</span><span class="p">(</span><span class="s1">&#39;localhost:6379&#39;</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'><span class="nv">$args</span> <span class="o">=</span> <span class="k">array</span><span class="p">(</span>
</span><span class='line'>    <span class="s1">&#39;name&#39;</span> <span class="o">=&gt;</span> <span class="s1">&#39;Chris&#39;</span>
</span><span class='line'><span class="p">);</span>
</span><span class='line'><span class="nx">Resque</span><span class="o">::</span><span class="na">enqueue</span><span class="p">(</span><span class="s1">&#39;default&#39;</span><span class="p">,</span> <span class="s1">&#39;My_Job&#39;</span><span class="p">,</span> <span class="nv">$args</span><span class="p">);</span>
</span><span class='line'><span class="cp">?&gt;</span><span class="x"></span>
</span></code></pre></td></tr></table></div></figure>


<p>其中第一個參數 <code>default</code> 就是你的 queue 名稱，例如你可以設定 notify, mail, image 之類，至於為什麼要這樣設計，在後面的篇幅再敘述。</p>

<p>值得一提的是，在原 ruby 版 rescue 每個 Job 屬於哪個 queue 是直接定義在 class 中的，PHP 版則是 enqueue 時才傳入，不知道為什麼要這樣設計，可能會導致一些意料之外的結果，需要注意。</p>

<p>PHP-Resque 的使用方法大致就是這樣，接下來講一些其他的小細節。</p>

<h2>Hooks</h2>

<p>PHP-Resque 可以定義 Event Hooks 讓你能在相對應的事件發生時執行你想要的動作。支援的事件有很多，請各位自行參考原專案的 README。在專案目錄下的 extra 目錄下有 sample.plugin.php 可以看 Event hook 的範例寫法。</p>

<p>有一點需要注意的是，很直覺我們會把這隻 sample.plugin.php 丟到 APP_INCLUDE 變數中，這樣沒錯，但要注意跟 enqueue 有關的 event 並不是由 worker 來觸發，因此你在新增 Job 的那段程式也需要引入 sample.plugin.php 才能觸發到 <code>AFTERENQUEUE</code> 。</p>

<h2>監控</h2>

<h3>resque-web</h3>

<p>前面有提到可以直接使用 resque-web 來監控 PHP-Resque 的狀態，相當建議使用，非常清楚易懂，要看 Redis 相關的數據也可以看，不用進 redis-cli 自己打指令。</p>

<p>安裝方法：<code>gem install resque</code></p>

<p>執行：<code>resque-web -p 3000</code> 即可運行在 3000 port。</p>

<p>首頁有 live reload 按鈕可以按， debug 時非常方便。</p>

<p>screenshot: <img src="http://blog.hsatac.net/images/wp-uploads/2012/01/resque-web.jpg"></p>

<h3>Supervisord</h3>

<p>在專案的 extra 目錄下另有 resque.monit 檔案，這是供 <a href="http://supervisord.org/">Supervisord</a> 使用的設定檔。他會在 worker 吃掉 300MB 以上的記憶體，或者是跑了 10 次輪迴後砍掉重開。可以參考看看。</p>

<h3>proctitle</h3>

<p>如果你 <code>ps | grep resque</code> 只會看到 <code>php resuqe.php</code> 的訊息，還記得 Worker 會 fork 出一個 process 來執行 Job 嗎？這樣就有兩倍的 processes 但是你完全分不出來哪個是哪個。原本 ruby 版本的設計是可以輕易看出 Worker fork 了哪個 process 而被 fork 出來的正在執行什麼工作。</p>

<p>Ruby 只要改 <code>$0</code> 就可以了， PHP 就沒這麼簡單了，要使用 <code>setproctitle</code> 。</p>

<p>但是這要安裝 pecl 的 <code>proctitle</code> 模組才能使用。</p>

<p>安裝方式：<code>pecl install proctitle channel://pecl.php.net/proctitle-0.1.1</code></p>

<p>記得要去 php.ini 讀進 .so 的 extension 。</p>

<p>完成後再執行 <code>ps -e -o pid,command | grep [r]esque</code> 時，就會從原本的</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="x">10486 php resque.php</span>
</span><span class='line'><span class="x">10487 php resque.php</span>
</span></code></pre></td></tr></table></div></figure>


<p>變成好讀易懂的：</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="x">10621 resque-1.0: Waiting for notify,mail,image,default</span>
</span><span class='line'><span class="x">10622 resque-1.0: Forked 10632 at 2012-01-16 13:42:55</span>
</span><span class='line'><span class="x">10632 resque-1.0: Processing default since 2012-01-16 13:42:55</span>
</span></code></pre></td></tr></table></div></figure>


<h2>佈署</h2>

<p>之前提到可以除了預設的 default 以外，還可以設定不同的 queue，為什麼要這樣做呢？除了執行優先權外，(撈 queue 時會按你給 worker 的設定，在前面 queue 的會先撈，就會先執行到) 還有多伺服器佈署的原因。</p>

<p>假如今天你有個 queue 專門要處理使用者圖片的東西，當然一般圖片會有自己的伺服器。於是在你的主 web 伺服器上你就可以執行 <code>QUEUE=notify,mail</code> 而在圖片伺服器上就可以執行 <code>QUEUE=images</code> 的 worker。</p>

<p>另外就是由於 Worker 啟動時已經將 <code>APP_INCLUDE</code> 的檔案都讀入，持續執行。因此如果有修改引入的 Job 或 hook plugin 等檔案的話，deploy 時要將 worker 停止，重新啟動才會讀入新的 <code>APP_INCLULDE</code> 檔案。</p>

<h2>已知問題</h2>

<p>首先，PHP-Resque 使用的是 <a href="https://github.com/jdp/redisent">Redisent</a> 這套 Redis interface。但因為和另一套 php module <a href="http://code.google.com/p/phpredis/">phpredis</a> 同樣都定義了 RedisException 這個類別，所以會衝突，必須把 phpredis 移除才能使用。</p>

<p>再來，在部屬時常常 REDIS_BACKEND 是設到別台機器的，而且一般我們都會開不只一個 worker ，這時候有一個已知 issue 就是有時 lpop 拉回來的 Job 錯誤，是一個陣列，導致噴出 json_decode 的錯誤，而且這個 Job 就不會執行，會 missing 。 (see <a href="https://github.com/chrisboulton/php-resque/issues/32">#32</a>)</p>

<p>目前還不清楚確實問題所在，不過有一個 workaround 的解法是，不要用 <code>COUNT=5</code> 去開，而是設 <code>COUNT=1</code> 然後執行 5 次，就不會有這個問題產生。</p>

<h2>結語</h2>

<p>Resque 真的是一個很棒很輕巧的設計，感謝有人把它 porting 到 PHP 。希望越來越多人來使用，一起來發展維護 PHP-Resque。</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[在 CentOs 5 上升級 Redis 2.4.5]]></title>
    <link href="http://blog.hsatac.net/2012/01/upgrade-redis245-on-centos5/" />
    <updated>2012-01-05T13:51:00+08:00</updated>
    <id>http://blog.hsatac.net/2012/01/upgrade-redis245-on-centos5</id>
    <content type="html"><![CDATA[<p>CentOS 5 上的 Redis 套件只有到 2.0
最近用一套 <a href="https://github.com/chrisboulton/php-resque">PHP-Resque</a> 需求 Redis 2.2 以上，只好手動升級了。</p>

<p>首先抓下最新穩定版解壓</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>wget http://redis.googlecode.com/files/redis-2.4.5.tar.gz
</span><span class='line'>tar zxvf redis-2.4.5.tar.gz
</span><span class='line'>cd redis-2.4.5
</span><span class='line'>make</span></code></pre></td></tr></table></div></figure>


<p>跟原本的 redis 2.0 裝在同一個目錄</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>sudo make PREFIX=/usr install</span></code></pre></td></tr></table></div></figure>


<p>再把新的 config 檔蓋過去</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>sudo cp redis.conf /etc/</span></code></pre></td></tr></table></div></figure>


<p>為了讓原本的 init script 正常運作
redis.conf 要稍微修改</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>daemonize yes
</span><span class='line'>...
</span><span class='line'>pidfile /var/run/redis/redis.pid</span></code></pre></td></tr></table></div></figure>


<p>原本 redis-server 是裝在 /usr/sbin 新的是裝在 /usr/bin
把 /usr/sbin/redis-server 覆蓋過去</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>sudo mv /usr/bin/redis-server /usr/sbin/</span></code></pre></td></tr></table></div></figure>


<p>大功告成。</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[用 scrpit 指令來紀錄輸出及輸入]]></title>
    <link href="http://blog.hsatac.net/2011/12/record-terminal-using-script/" />
    <updated>2011-12-29T14:59:00+08:00</updated>
    <id>http://blog.hsatac.net/2011/12/record-terminal-using-script</id>
    <content type="html"><![CDATA[<p>假設我們現在要執行一個重要的動作，想要紀錄 terminal 下面每一個輸出和輸入，當然我們可以在每個指令後面用 <code>cmd &gt; filename</code> 把輸出導向 log 檔，但如果是一連串的動作時就很不方便了。</p>

<p>unix 系列內建一個指令叫 <code>script</code> ，他可以很方便的紀錄你每一個輸出和輸入。詳細用法可以參考 <code>man script</code> 。</p>

<p>在這邊講兩個常用的方法，一個是 <code>script log.txt</code> 會把紀錄存到 log.txt, 用 <code>script -a log.txt</code> 就可以把新的 log append 到檔案後，不會蓋掉原本檔案。當你動作結束，想停止紀錄時，只要打 <code>exit</code> 就可以停止紀錄。</p>

<p>另一個是 <code>script -C "ls -al" log.txt</code> 他會把你指定的指令存到 log.txt 中，這個用法的不需輸入 <code>exit</code> 。</p>

<p>如果你的 .bash_profile 裏面有用到一些自訂的函數例如 git-autocompletion 之類，那你在使用 script 的時候可能會發現每下一個指令都告訴你 <code>command not found</code>。正確的解法是把你的 function 移到 .bashrc 中，在 .bash_profile 裏面去 source .bashrc 即可。</p>

<p>最後說明一下 log 檔的觀看方式，因為 script 會把所有東西都紀錄下來，包括控制碼這些，所以可以用 <code>less -r log.txt</code> 或 <code>more log.txt</code> 來觀看。</p>

<p>如果需要把 log 的控制碼去掉，可以參考下面這個 script:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
</pre></td><td class='code'><pre><code class='perl'><span class='line'><span class="c1">#!/usr/bin/env perl</span>
</span><span class='line'><span class="k">while</span> <span class="p">(</span><span class="o">&lt;&gt;</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="sr">s/ \e[ #%()*+\-.\/]. |</span>
</span><span class='line'><span class="sr">       (?:\e\[|\x9b) [ -?]* [@-~] | # CSI ... Cmd</span>
</span><span class='line'><span class="sr">       (?:\e\]|\x9d) .*? (?:\e\\|[\a\x9c]) | # OSC ... (ST|BEL)</span>
</span><span class='line'><span class="sr">       (?:\e[P^_]|[\x90\x9e\x9f]) .*? (?:\e\\|\x9c) | # (DCS|PM|APC) ... ST</span>
</span><span class='line'><span class="sr">       \e.|[\x80-\x9f] //xg</span><span class="p">;</span>
</span><span class='line'>    <span class="k">print</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>



]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Vim runtime 不需存檔檢查 PHP 語法]]></title>
    <link href="http://blog.hsatac.net/2011/12/vim-php-runtime-syntax-check-without-saving-file/" />
    <updated>2011-12-22T17:29:00+08:00</updated>
    <id>http://blog.hsatac.net/2011/12/vim-php-runtime-syntax-check-without-saving-file</id>
    <content type="html"><![CDATA[<p>之前 vim PHP syntax check 都是跟存檔綁在一起，同事想要不用存檔就可以檢查，就弄了一下。</p>

<div><script src='https://gist.github.com/1496197.js?file='></script>
<noscript><pre><code>  set errorformat=%m\ in\ %f\ on\ line\ %l
  if !exists('*PHPsynCHK')
    function! PHPsynCHK()
      ccl
      let winnum = winnr()
      let linenum = line('.')
      let colnum = col('.')
      silent execute &quot;%!php -l -f /dev/stdin | sed 's/\\/dev\\/stdin/&quot;.bufname(&quot;%&quot;).&quot;/g' &gt;.vimerr; cat&quot;
      silent cf .vimerr
      cw
      execute winnum . &quot;wincmd w&quot;
      silent undo
      silent cf
      if 1 == len(getqflist())
         call cursor(linenum, colnum)
      endif
    endfunction
  endif
</code></pre></noscript></div>


<p>用法直接 <code>:call PHPsynCHK()</code> 即可，可以自己綁定熱鍵。</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Bash PS1 補滿]]></title>
    <link href="http://blog.hsatac.net/2011/12/bash-ps1-fill/" />
    <updated>2011-12-20T16:00:00+08:00</updated>
    <id>http://blog.hsatac.net/2011/12/bash-ps1-fill</id>
    <content type="html"><![CDATA[<p>今天 Even Wu 在 facebook 上問了一個問題：他的 Bash PS1 要補滿 dash 到換行為止，感覺很有趣，稍微研究了一下。</p>

<p>首先要取得 term 的寬度，這個很容易直接抓 <code>$COLUMNS</code> 就好。</p>

<p>再來要抓原本 PS1 的長度，原本打算用 <code>$PWD</code> 去抓，不過 \w 碰到自己的家目錄會變 <code>~</code> 所以長度不對，這邊要自己處理一下：</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>  <span class="k">if</span> <span class="o">[</span> <span class="s2">&quot;$HOME&quot;</span> <span class="o">==</span> <span class="s2">&quot;$PWD&quot;</span> <span class="o">]</span>
</span><span class='line'>  <span class="k">then</span>
</span><span class='line'><span class="k">    </span><span class="nv">newPWD</span><span class="o">=</span><span class="s2">&quot;~&quot;</span>
</span><span class='line'>  <span class="k">elif</span> <span class="o">[</span> <span class="s2">&quot;$HOME&quot;</span> <span class="o">==</span>  <span class="s2">&quot;${PWD:0:${#HOME}}&quot;</span> <span class="o">]</span>
</span><span class='line'>  <span class="k">then</span>
</span><span class='line'><span class="k">    </span><span class="nv">newPWD</span><span class="o">=</span><span class="s2">&quot;~${PWD:${#HOME}}&quot;</span>
</span><span class='line'>  <span class="k">else</span>
</span><span class='line'><span class="k">    </span><span class="nv">newPWD</span><span class="o">=</span><span class="nv">$PWD</span>
</span><span class='line'>  <span class="k">fi</span>
</span></code></pre></td></tr></table></div></figure>


<!--more-->


<p>然後塞成跟原本 PS1 一樣的 temp 字串來算長度，最後把 term width 減去 temp 就可以抓到長度了，再作補滿的動作即可。</p>

<p>最後結果如下：</p>

<div><script src='https://gist.github.com/1500143.js?file='></script>
<noscript><pre><code>function git_branch {
ref=$(git symbolic-ref HEAD 2&gt; /dev/null) || return;
echo &quot;(&quot;${ref#refs/heads/}&quot;) &quot;;
}

function git_since_last_commit {
now=`date +%s`;
last_commit=$(git log --pretty=format:%at -1 2&gt; /dev/null) || return;
seconds_since_last_commit=$((now-last_commit));
minutes_since_last_commit=$((seconds_since_last_commit/60));
hours_since_last_commit=$((minutes_since_last_commit/60));
minutes_since_last_commit=$((minutes_since_last_commit%60));

echo &quot;${hours_since_last_commit}h${minutes_since_last_commit}m &quot;;
}

unset temp

function prompt_command {

  if [ $HOME == $PWD ]
  then
    newPWD=&quot;~&quot;
  elif [ $HOME ==  ${PWD:0:${#HOME}} ]
  then
    newPWD=&quot;~${PWD:${#HOME}}&quot;
  else
    newPWD=$PWD
  fi

  TERMWIDTH=${COLUMNS}

  local temp=&quot;→ [ ${newPWD} ] $(git_branch)$(git_since_last_commit)&quot;
  let fillsize=${TERMWIDTH}-${#temp}
  if [ &quot;$fillsize&quot; -gt &quot;0&quot; ]
  then
    fill=&quot;----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------&quot;
    fill=&quot;${fill:0:${fillsize}}&quot;
  fi
}

PROMPT_COMMAND=prompt_command
PS1=&quot;\[\033[1;31m\]→\[\033[0m\] \[\033[0;36m\][ \[\033[1;32m\]\${newPWD}\[\033[0;36m\] ] \[\033[0m\]\[\033[1;31m\]\$(git_branch)\[\033[0m\]\$(git_since_last_commit)\${fill}\n$ &quot;</code></pre></noscript></div>



]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Logitech G300 on ArchLinux]]></title>
    <link href="http://blog.hsatac.net/2011/11/logitech-g300-on-archlinux/" />
    <updated>2011-11-30T00:00:00+08:00</updated>
    <id>http://blog.hsatac.net/2011/11/logitech-g300-on-archlinux</id>
    <content type="html"><![CDATA[<p>前陣子入手了 Logitech G300 這支滑鼠，相當優秀。<br />
他的特色是把快速鍵記在滑鼠內，不需要安裝任何驅動程式。<br />
其原理是送出「真正的鍵盤訊號」，因此可以相容所有遊戲。</p>

<p>不過在我的 ArchLinux 下這支 G300 使用不太正常<br />
當我按下滑鼠鍵後，游標會飄移到螢幕左上方。<br />
經過測試後，判斷是他送出的 keyboard 訊號問題<br />
只要把 keyboard disable 掉就可以了。<!--more-->
<pre lang="bash">xinput list</pre>
應該可以看到各有一個 Logitech G300 的鍵盤和滑鼠，後面會有 id 例如 12
<pre lang="bash">xinput list-props 12</pre>
會看到類似
<pre lang="bash">Device Enabled (132)</pre>
再下
<pre lang="bash">xinput set-prop 12 132 0</pre>
就可以把這個裝置 disable 掉。</p>

<p>但是每次都要這樣查很麻煩，而且這號碼不是固定的<br />
所以我寫成 script 可以放在 xinitrc 裏面去自動執行
<pre lang="bash">#!/bin/sh
DEVICE_ID=`xinput list |  grep "Logitech Gaming Mouse G300" | grep keyboard | sed 's/.*id=\([0-9]*\).*/\1/'`

if xinput -list-props $DEVICE_ID | grep "Device Enabled" | grep "1$" &gt; /dev/null
then
    xinput set-int-prop $DEVICE_ID "Device Enabled" 8 0
fi
</pre>
接著還有一個小問題，就是每當機器 wake up 的時候，滑鼠又會跑掉了，那有沒有辦法在 wake up 時執行這段程式呢？<br />
在 /etc/pm/sleep.d/ 下<br />
新增一個 script 讓他去執行上一段程式就可以了。
<pre lang="bash">!/bin/sh
# 90G300: suspend/wakeup Logitech G300 devices

case "$1" in
hibernate|suspend)
;;
thaw|resume)
/home/cat/.xinitrc.d/50-logitech-g300-mouse
;;
*) exit $NA
;;
esac
</pre>

<p>這個 solution 也同步更新到 Archwiki 上，這就是社群的力量啊！</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Archlinux 推廣]]></title>
    <link href="http://blog.hsatac.net/2011/11/archlinux/" />
    <updated>2011-11-30T00:00:00+08:00</updated>
    <id>http://blog.hsatac.net/2011/11/archlinux</id>
    <content type="html"><![CDATA[<p><img class="alignnone" title="archlinux_logo" src="http://d11xdyzr0div58.cloudfront.net/main-20111101/media/logos/archlinux-logo-dark-90dpi.png" alt="" width="75%" /></p>

<p>一個月前，因為工作環境轉換，決定趁機開始使用 Linux 作為日常桌面環境。以往都用 ubuntu 但不甚滿意，這次決定試試看 Archlinux，果然沒有讓我失望。<!--more-->
<h1>Why Arch?</h1>
Archlinux 設計的理念是「簡單」、「正確」、「使用者至上」、「開放」、「自由」(參見 <a href="https://wiki.archlinux.org/index.php/The_Arch_Way_(%E6%AD%A3%E9%AB%94%E4%B8%AD%E6%96%87)" target="_blank">Arch 之道</a>)。</p>

<p>他採取滾動式升級 (rolling release system)，不再有每次大版本升級的噩夢。<br />
他的套件管理 pacman 相當優秀，更有社群貢獻的套件庫 AUR，安裝軟體簡單又不髒手。
<a href="https://wiki.archlinux.org/" target="_blank">Archwiki</a> 應該是網路上資料最豐富最齊全的 linux wiki 了，不管什麼疑難雜症都可以在裏面找到。<br />
Archlinux 安裝完是一個乾淨輕巧的系統，你可以依照自己的喜好打造自己的工作環境。
<h1>Install</h1>
一開始的安裝可以跟著這兩篇 wiki：
<ul>
	<li><a href="https://wiki.archlinux.org/index.php/Official_Installation_Guide" target="_blank">Official Installation Guide</a></li>
	<li><a href="https://wiki.archlinux.org/index.php/Beginners%27_Guide" target="_blank">Beginner&#8217;s Guide</a></li>
</ul>
其實安裝很簡單，光碟插進去以後下一步就結束了，不過選項還是要稍微看一下。
<h2>套件管理</h2>
安裝完以後先把 pacman mirror 只留台灣站，做一次系統升級 sudo pacman -Syu<br />
再想辦法安裝 AUR (Arch User Repositories) 輔助程式。<br />
比較有名的是 Yaourt 不過已經停止開發了，我推薦使用 packer。<br />
想辦法安裝 packer 以後，離成功就不遠啦！
<div>
<ul>
	<li><a href="https://wiki.archlinux.org/index.php/Pacman_(%E6%AD%A3%E9%AB%94%E4%B8%AD%E6%96%87)" target="_blank">pacman 說明</a></li>
	<li><a href="https://wiki.archlinux.org/index.php/AUR" target="_blank">AUR 說明</a></li>
	<li><a href="https://wiki.archlinux.org/index.php/AUR_Helpers" target="_blank">AUR helper 說明</a></li>
</ul>
</div>
<h2>桌面環境</h2>
桌面環境有許多選擇，例如 gnome, kde, xfce4, lxde 等等，可以按自己的喜好做選擇。<br />
安裝過程可以參考 archwiki，當然也有許多 Archlinux 分支出去，隨附 Desktop Environment 的發行版：<br />
例如 kde 的 <a href="http://chakra-linux.org/about.html" target="_blank">Chakra</a> 、gnome 的 <a href="http://www.kahelos.org/" target="_blank">KahelOS</a> 、openbox 的 <a href="http://archbang.org/" target="_blank">Archbang</a> 等等，這裡有<a href="https://wiki.archlinux.org/index.php/Arch_Based_Distributions_(Active)" target="_blank">清單一覽</a>。<br />
這些桌面發行版，除了簡化安裝流程外，通常也會針對桌面環境做設定和優化，想省時間的話不妨可以考慮。
<h2>中文使用</h2>
中文使用者的兩大問題不外乎就是字型和輸入法。<br />
字型的部份可以參考<a href="http://imxie.net/2010/06/basic-lcd-font-config-on-archlinux.htm" target="_blank">這篇文章</a>來做設定。<br />
我中文字型是選擇 Hiragino Sans GB ，從我的 Mac 上複製過來，效果非常好。<br />
輸入法的部份大概就 scim, gcin, ibus 選一套，ibus 我用不太習慣，用了一陣子 scim ，發現不是很穩定，目前改用 gcin ，使用狀況良好。
<h1>結語</h1>
本來有很多踩到的雷想寫，後來想想都太瑣碎了。<br />
玩 Arch 只要把握一個原則：查 wiki ，大概什麼問題都可以迎刃而解。<br />
Linux DE 的原罪就是選擇太多，通常要自己試用、設定後才能符合自己的需求。<br />
在這之中可能會有很多挫折，不過解決問題的過程也是一種喜悅。<br />
只要肯花時間，絕對能把環境打造到你喜歡的樣子。<br />
一起來享受 Arch 吧！</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Redmine + Bundler 復活記]]></title>
    <link href="http://blog.hsatac.net/2011/09/redmine-bundler-%E5%BE%A9%E6%B4%BB%E8%A8%98/" />
    <updated>2011-09-30T00:00:00+08:00</updated>
    <id>http://blog.hsatac.net/2011/09/redmine-bundler-復活記</id>
    <content type="html"><![CDATA[<p>老實說，不記得之前是動了什麼，總之我的佈署 apache + passenger + ree 環境<br />
redmine 爆炸了。推測應該是 gem 的關係。<br />
上網看了一下， rails 2.3 只支援 rubygems 1.7<br />
就先把 rubygems downgrade 回來
<pre lang="bash">gem update --system 1.7</pre></p>

<p>和 tkalu, xdite, ihower, 以及小蟹詢問了各種可能的解決方案後<br />
確定我應該是要用 bundler 來管理一下 redmine 的 gems</p>

<p>根據 ihower 提供的資訊， redmine 有一個內建 bundler 的 fork 版<br />
搜尋了一下找到了 https://www.chiliproject.org/<br />
把他的 <a href="https://github.com/chiliproject/chiliproject/blob/unstable/Gemfile" target="_blank">Gemfile</a> 借過來一用</p>

<p>再按照 <a href="http://gembundler.com/rails23.html" target="_blank">Bundler 官網上的 Rails 2 教學</a>
來設定，果然成功把我的 redmine 救了回來！</p>

<p>chiliproject 的 Gemfile 可能要稍加修改，例如他用 rails 2.3.14，可以改成 redmine 官網支援的 2.3.11<br />
然後一些沒用到的 gem 例如 pg 可以移除。</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Rake 0.9 爆炸解法]]></title>
    <link href="http://blog.hsatac.net/2011/09/rake-0-9/" />
    <updated>2011-09-20T00:00:00+08:00</updated>
    <id>http://blog.hsatac.net/2011/09/rake-0-9</id>
    <content type="html"><![CDATA[<p>由於 rake 0.9 跟之前的不相容，因此裝了以後大概都會碰到這堆錯誤：
<pre lang="bash">/Users/cat/.rvm/gems/ruby-1.9.2-p290@global/gems/rake-0.9.2/lib/rake/version.rb:4: warning: already initialized constant MAJOR
/Users/cat/.rvm/gems/ruby-1.9.2-p290@global/gems/rake-0.9.2/lib/rake/version.rb:5: warning: already initialized constant MINOR
/Users/cat/.rvm/gems/ruby-1.9.2-p290@global/gems/rake-0.9.2/lib/rake/version.rb:6: warning: already initialized constant BUILD
/Users/cat/.rvm/gems/ruby-1.9.2-p290@global/gems/rake-0.9.2/lib/rake/version.rb:3: warning: already initialized constant NUMBERS
/Users/cat/.rvm/gems/ruby-1.9.2-p290@global/gems/rake-0.9.2/lib/rake/version.rb:9: warning: already initialized constant VERSION
/Users/cat/.rvm/gems/ruby-1.9.2-p290@global/gems/rake-0.9.2/lib/rake.rb:26: warning: already initialized constant RAKEVERSION
/Users/cat/.rvm/gems/ruby-1.9.2-p290@global/gems/rake-0.9.2/lib/rake/early_time.rb:17: warning: already initialized constant EARLY
/Users/cat/.rvm/gems/ruby-1.9.2-p290@global/gems/rake-0.9.2/lib/rake/alt_system.rb:32: warning: already initialized constant WINDOWS
/Users/cat/.rvm/gems/ruby-1.9.2-p290@global/gems/rake-0.9.2/lib/rake/application.rb:28: warning: already initialized constant DEFAULT_RAKEFILES
WARNING: Possible conflict with Rake extension: String#ext already exists
WARNING: Possible conflict with Rake extension: String#pathmap already exists
/Users/cat/.rvm/gems/ruby-1.9.2-p290@global/gems/rake-0.9.2/lib/rake/task_arguments.rb:73: warning: already initialized constant EMPTY_TASK_ARGS
/Users/cat/.rvm/gems/ruby-1.9.2-p290@global/gems/rake-0.9.2/lib/rake/invocation_chain.rb:49: warning: already initialized constant EMPTY
/Users/cat/.rvm/gems/ruby-1.9.2-p290@global/gems/rake-0.9.2/lib/rake/file_utils.rb:10: warning: already initialized constant RUBY
/Users/cat/.rvm/gems/ruby-1.9.2-p290@global/gems/rake-0.9.2/lib/rake/file_utils.rb:84: warning: already initialized constant LN_SUPPORTED
/Users/cat/.rvm/gems/ruby-1.9.2-p290@global/gems/rake-0.9.2/lib/rake/dsl_definition.rb:143: warning: already initialized constant Commands
/Users/cat/.rvm/gems/ruby-1.9.2-p290@global/gems/rake-0.9.2/lib/rake/file_list.rb:44: warning: already initialized constant ARRAY_METHODS
/Users/cat/.rvm/gems/ruby-1.9.2-p290@global/gems/rake-0.9.2/lib/rake/file_list.rb:47: warning: already initialized constant MUST_DEFINE
/Users/cat/.rvm/gems/ruby-1.9.2-p290@global/gems/rake-0.9.2/lib/rake/file_list.rb:51: warning: already initialized constant MUST_NOT_DEFINE
/Users/cat/.rvm/gems/ruby-1.9.2-p290@global/gems/rake-0.9.2/lib/rake/file_list.rb:55: warning: already initialized constant SPECIAL_RETURN
/Users/cat/.rvm/gems/ruby-1.9.2-p290@global/gems/rake-0.9.2/lib/rake/file_list.rb:61: warning: already initialized constant DELEGATING_METHODS
/Users/cat/.rvm/gems/ruby-1.9.2-p290@global/gems/rake-0.9.2/lib/rake/file_list.rb:364: warning: already initialized constant DEFAULT_IGNORE_PATTERNS
/Users/cat/.rvm/gems/ruby-1.9.2-p290@global/gems/rake-0.9.2/lib/rake/file_list.rb:370: warning: already initialized constant DEFAULT_IGNORE_PROCS
/Users/cat/.rvm/gems/ruby-1.9.2-p290@global/gems/rake-0.9.2/lib/rake.rb:64: warning: already initialized constant FileList
/Users/cat/.rvm/gems/ruby-1.9.2-p290@global/gems/rake-0.9.2/lib/rake.rb:65: warning: already initialized constant RakeFileUtils
rake aborted!
stack level too deep</pre></p>

<p>(See full trace by running task with &#8211;trace)
<!--more--></p>

<p>解決的方法很簡單，你知道、我知道、獨眼龍也知道：就是 bundle exec rake</p>

<p>但是一直打一直打實在很煩。寫 Ruby 的時候，當你開始覺得有重複的打字作業的時候，就表示事情不太對勁了&#8230;&#8230;</p>

<p>那該怎麼辦呢？<del>你怎麼不問問神奇海螺呢？</del></p>

<p>Google 了一下，發現 <a href="http://ihower.tw/blog/archives/5762" target="_blank">ihower 的這個解法</a>不錯。</p>

<p>簡單說，在你的目錄下先下
<pre lang="bash">bundle install --binstubs</pre>
這個指令會把 Gemfile 裡面的執行檔安裝在專案目錄的 bin 目錄下面。</p>

<p>接著在專案目錄開一個 .rvmrc 裡面填
<pre lang="bash">export PATH="./bin:$PATH"</pre>
這樣當你執行 rake 的時候 rvm 就會幫你抓到專案目錄下的 bin 下的 rake 執行檔了！</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[CloudAAA 雲端大亂鬥簡記]]></title>
    <link href="http://blog.hsatac.net/2011/06/cloudaaa/" />
    <updated>2011-06-23T00:00:00+08:00</updated>
    <id>http://blog.hsatac.net/2011/06/cloudaaa</id>
    <content type="html"><![CDATA[<p>這次 CloudAAA 活動是由 <a href="http://groups.google.com/group/cloudtw?pli=1">CloudTW</a> 與 <a href="http://www.taipei-gtug.org/">Taipei-GTUG</a> 合辦<br />
借到了精誠資訊的大樓，相當棒的一個場地。<br />
不得不稱讚主辦單位，一進來打開電腦四個 AP 速度又快，足顯誠意<br />
食物飲水也很精美充足，真的是沒什麼好挑剔的。</p>

<p>一開始 Hank Lin 主講 aws 的部份<br />
Hank 一開場就直接嗆「aws feature 比微軟和 google 多的多」<br />
因為我本身對 aws 比較沒有深入研究<br />
加上 Hank 講得實在是有點快<br />
只略約有印象好像介紹了一些 Route 53 的新特色<br />
還有 Oracle 的部份可以用自己的 license ，沒有的話可以用租的<br />
然後<del datetime="2011-06-23T01:26:58+00:00"><a href="http://www.cite.com.tw/product_info.php?products_id=18865">買他的書</a></del>。<br />
(認識的要買可以找我，打6折)<!--more--></p>

<p>再來是微軟的 Tom 介紹 Windows Azure<br />
Windows Azure 應該大家比較沒有接觸過，應該都很有興趣<br />
簡單的說：「aws 有的微軟都有，價格只會便宜不會貴」<br />
然後展示了一下 WebMatrix 這套 IDE 搭配 Windows Azure 的佈署方式<br />
整合的相當好的一個 IDE，感覺開發起來也很方便，習慣 .net 的用戶應該很容易能夠上手<br />
WebMatrix 這套 IDE 是免費的，現場微軟也提供了一組 30 天 Windows Azure 試用序號
<p style="text-align: center;"><a href="http://blog.hsatac.net/images/wp-uploads/2011/06/3648187_0b55ff2678e6a623989d55396bba56311.jpg"><img class="aligncenter size-full wp-image-468" title="3648187_0b55ff2678e6a623989d55396bba5631[1]" src="http://blog.hsatac.net/images/wp-uploads/2011/06/3648187_0b55ff2678e6a623989d55396bba56311.jpg" alt="" width="480" height="640" /></a></p>
使用 windows live 帳號登入 http://windowsazurepass.com/ 輸入 SSAPERUZAWT<br />
然後 ericsk 上官大大有提到 SQL Azure 使用 MSSQL 的話可以做 scalibility<br />
這點我還滿有興趣的，目前 GAE 和 aws 似乎都做不到<br />
詳細實做方式可能還要再研究一下。</p>

<p>ericsk 上官大大提供的相關資料：
<a href="http://blog.smarx.com/posts/node-js-ruby-and-python-in-windows-azure-my-mix-talk">其他語言在 Windows Azure</a>
<a href="http://webpi.dotblogs.com.tw/">下載微軟 Web Platform 抽 Kinect</a></p>

<p>Tom 在 session 中提到的這篇文章：
<a href="http://highscalability.com/blog/2010/5/26/end-to-end-performance-study-of-cloud-services.html">有 AAA 的 performance 比較</a></p>

<p>接下來的時間因為 Google 的講者 Ikai 還在機場過來的路上，因此先進行了 Lightning Talk<br />
cloudena 在徵人<br />
PyConTW 和 HIT 2011 歡迎報名 (PyConTW 早就爆滿啦)<br />
Ken 介紹了自己開發的<a href="http://www.ps158.com/blog/archives/1664">活動簽到 App</a> 概念很不錯</p>

<p>最後 Ikai 終於到場了，稍微介紹了一下 GAE 和 GO<br />
GAE 的部份跟以前認知的差不多，<br />
GO 感覺滿吸引人的</p>

<p>我提供的 GO 相關文章：<br />
剛好 Hack News 那邊同時跳出來XD<br />
http://blog.kowalczyk.info/article/Go-vs-Python-for-a-simple-web-server.html</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[讓 Empathy 支援 P4-Context]]></title>
    <link href="http://blog.hsatac.net/2011/06/empathy-p4-context/" />
    <updated>2011-06-12T00:00:00+08:00</updated>
    <id>http://blog.hsatac.net/2011/06/empathy-p4-context</id>
    <content type="html"><![CDATA[<p>這兩天灌了 Ubuntu 11.04 在玩<br />
內建的 Empathy 即時通訊軟體很強大，整合了多種 im<br />
但是他的 msn 不支援 msn protocol 的 P4-Context tag<br />
最直接的影響就是 m群看不到是誰在說話。<br />
看了一下發現他底層是用 python-papyon 這套 msn lib<br />
於是就可以直接動手修改啦！</p>

<p>先開啟 /usr/share/pyshared/papyon/conversation.py<br />
找到 387 行：
<pre lang="python" line="387">        if message_type == 'text/plain':
            msg = ConversationMessage(unicode(message.body, message_encoding),
                    TextFormat.parse(message_formatting),
                    self.__last_received_msn_objects)
            try:
                display_name = message.get_header('P4-Context')</pre>
<!--more-->
將這段改成：
<pre lang="python" line="387">       if message_type == 'text/plain':
            try:
                msg = ConversationMessage(unicode("["+message.get_header('P4-Context')+"]"+message.body, message_encoding),
                        TextFormat.parse(message_formatting),
                        self.__last_received_msn_objects)
            except KeyError:
                msg = ConversationMessage(unicode(message.body, message_encoding),
                        TextFormat.parse(message_formatting),
                        self.__last_received_msn_objects)
            try:
                display_name = message.get_header('P4-Context')</pre>
存檔後重新啟動 empathy 就可以了！</p>

<p>ps. 請自行注意 python 縮排</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Better Array, Better PHP]]></title>
    <link href="http://blog.hsatac.net/2011/06/better-array-better-php/" />
    <updated>2011-06-11T00:00:00+08:00</updated>
    <id>http://blog.hsatac.net/2011/06/better-array-better-php</id>
    <content type="html"><![CDATA[<p>PHP 的 array() 大家都是詬病已久了，總是在想，要是能像其他語言一樣，用個中括號括起來就好那該有多好。
<p style="text-align: center;"><a href="http://blog.hsatac.net/images/wp-uploads/2011/06/betterphp.png"><img class="aligncenter size-full wp-image-445" title="betterphp" src="http://blog.hsatac.net/images/wp-uploads/2011/06/betterphp.png" alt="" width="446" height="393" /></a></p>
<!--more-->昨天剛好看到鐵神分享的這篇 <a href="http://www.xarg.org/2011/06/php-hacking/" target="_blank">PHP Hacking</a> ，作者把 PHP 修改了許多小地方，除了上述的新 array 語法外，還有許多新增函式和效能調校，感覺真的很不錯。</p>

<p>不過我最想要的只有 array 這個語法，而且不想被作者的版本綁死，於是我決定下載他的程式碼來研究一下如何修改。結果發現，只要改一行，就可以擁有這個功能！</p>

<p>以下紀錄一下我修改成功的過程，我開了一台乾淨的 Ubuntu 11.04 vm 出來測試。</p>

<p>首先抓好 PHP 5.3.6 的原始碼生肉，找到 Zend/zend_language_parser.y 這個檔案：</p>

<p>找到
<pre lang="c">  |  T_ARRAY '(' array_pair_list ')' { $$ = $3; }</pre>
這行，在下面多加一行
<pre lang="c">  |  '[' array_pair_list ']'         { $$ = $2; }</pre>
接著安裝一些必要的元件：
<pre lang="bash">sudo apt-get install apache
sudo apt-get install apache2-prefork-dev #要編譯成 libphp5.so 需要裝這個
sudo apt-get install libxml2-dev
sudo apt-get install re2c</pre>
接著還要安裝 <a href="http://www.gnu.org/software/bison/" target="_blank">bison</a> ，apt-get 裝的 bison 版本太舊不合用，可以自己去抓 2.3 版來編譯</p>

<p>bison 需要 m4, 所以編譯過程中有需要的話就 apt-get install m4 吧。</p>

<p>以上準備工作都做好後，就可以開始編譯 PHP 啦。
<pre lang="bash">./configure --prefix=/usr/local/lib/php5.3.6.infusion --with-apxs2=/usr/bin/apxs2
make && sudo make install</pre>
記得在 configure 的過程要注意有沒抓到 bison ，這是最重要的，如果沒抓到的話這個修改是不會有作用的。</p>

<p>都編完以後趕快
<pre lang="bash">a2enmod php5
sudo apachectl restart</pre>
來試試看有沒有成功吧！我編完以後，8245個測試都跑過了，應該是沒問題，enjoy it！</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[我的 vimrc for vim, win32 gvim, macvim]]></title>
    <link href="http://blog.hsatac.net/2011/05/my-vimrc-for-vim-win32-gvim-macvim/" />
    <updated>2011-05-18T00:00:00+08:00</updated>
    <id>http://blog.hsatac.net/2011/05/my-vimrc-for-vim-win32-gvim-macvim</id>
    <content type="html"><![CDATA[<p><a href="http://blog.hsatac.net/images/wp-uploads/2011/05/gvim.png"><img class="size-large wp-image-416 aligncenter" title="gvim" src="http://blog.hsatac.net/images/wp-uploads/2011/05/gvim-1024x649.png" alt="" width="393" height="249" /></a></p>

<p>最近在調整我的 vim 設定，目標是在 vim, win32 gvim, macvim 上都能有盡量相同的編輯體驗。<!--more--></p>

<p>先說明一下我的工作環境，我有一台 Mac mini server，平常會用 pietty 連上去改 code；有一台 Macbook Air ，使用 MacVim 開發，家中和公司使用的是 Win 7 64bit，使用放在 dropbox 的 portable gvim。</p>

<p>主要用到的 plugin 是 Command-T, taglist 以及 omnicomplete 。</p>

<p><a href="http://blog.hsatac.net/images/wp-uploads/2011/05/vim.png"><img class="aligncenter size-large wp-image-415" title="vim" src="http://blog.hsatac.net/images/wp-uploads/2011/05/vim-1024x605.png" alt="" width="368" height="218" /></a></p>

<p>一開始我用 <a href="https://github.com/vgod/vimrc" target="_blank">vgod 的 vimrc</a> 來當範本修改，詳細設定可以參考<a href="https://github.com/hSATAC/vimrc" target="_blank">我的 vimrc </a></p>

<p>主要的困難點大概有幾個：
<h2>Command-T</h2>
在 MacVim 上， Command-T 使用相當簡單，裝好以後直接執行
<pre lang="bash">ruby extconf.rb
make</pre>
之後就可以使用了。<br />
但純文字模式下的 vim 就沒這麼簡單了，我在 mac server 上重編的 +ruby vim 無論如何都沒辦法把編譯好的 plugin 載入。<br />
後來只好折衷直接使用 macvim 內置的 vim ，他在你的 MacVim.app/Contents/MacOS/Vim 。</p>

<p>這個檔案不管是複製或是 ln -s 到其他 path 執行，都會報錯，最後是用
<pre lang="bash">alias vim='PATH/MacVim.app/Contents/MacOS/Vim'</pre>
來解決。</p>

<p>不過這個用法有一個需要注意的地方，就是在 vim 中我們判斷 MacVim 一般會用
<pre lang="vim">has("gui_macvim")</pre>
來判斷，但用 MacVim 自帶的 Vim，這個判斷會成立。</p>

<p>因此要改用
<pre lang="vim">has("gui_macvim") && has("gui_running")</pre>
Windows 的部份比較麻煩，你要先安裝 <a href="http://rubyinstaller.org/downloads/" target="_blank">Ruby 和 DevKit</a> 才能編譯這個 plugin。</p>

<p>編譯：
<pre lang="bash">C:\Ruby192\DevKit\devkitvars.bat
cd yourvimfiles\plugins\ruby\command-t
ruby extconf.rb
make
make install</pre>
然後因為現在官網的 gvim 7.3.46 版只支援 ruby 1.9.1，要抓最新的 trunk code 下來編譯成 +ruby。</p>

<p>這個動作在 windows 實在不是很容易，所以這邊提供了<a href="http://dl.dropbox.com/u/7919509/gvim73.zip" target="_blank">編譯好的版本</a>。
<h2>taglist</h2>
taglist 需要 <a href="http://ctags.sourceforge.net/" target="_blank">Exuberant Ctags</a></p>

<p>這個部份 windows 平台反而單純，直接下載編譯好的執行檔丟到 vim 目錄下就好。</p>

<p>Mac 自帶的 ctags 不相容，所以需要抓新的來編。</p>

<p>我是直接用
<pre lang="bash">brew install ctags</pre>
讓各平台的 plugin 都能正常運作以後，最後就是設定一些快速鍵和 fix term 的問題，這邊就是個人偏好了，詳情可以直接看我的 <a href="https://github.com/hSATAC/vimrc" target="_blank">vimrc github</a></p>

<p>最後，如上所述，這份 vimrc 主要是在 mac 和 windows 使用，沒有在其他作業系統測試過。</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Firefox4 x WebM x Apache]]></title>
    <link href="http://blog.hsatac.net/2011/04/firefox4-x-webm-x-apache/" />
    <updated>2011-04-28T00:00:00+08:00</updated>
    <id>http://blog.hsatac.net/2011/04/firefox4-x-webm-x-apache</id>
    <content type="html"><![CDATA[<p><a rel="attachment wp-att-397" href="http://blog.hsatac.net/?attachment_id=397"><img class="size-full wp-image-397 alignleft" title="webm_open-media-project_logo[1]" src="http://blog.hsatac.net/images/wp-uploads/2011/04/webm_open-media-project_logo1.png" alt="" width="180" height="60" /></a> 今天在弄一些 WebM 的東西，同樣的頁面和影像檔在 chrome 都很正常，但是碰到 firefox 4 就會爛掉，可是 firefox 4 明明就支援 WebM 了啊</p>

<p>&nbsp;</p>

<p>後來做了幾個實驗，直接用 file:/// 開檔案，居然就正常了！ 但放到伺服器上，又出了問題。</p>

<p>survey 了一下，果然是 apache 處理 WebM 時 mimetype 沒有正確送出。</p>

<p>只要修改 /etc/apache2/mime.types 把 WebM 加進去就可以了
<pre lang="bash">video/webm webm</pre>
至於 chrome 為什麼會正常，只能猜測 chrome 有特別針對這個問題做優化吧&#8230;</p>

<p>有沒有 chrome 偷偷對 WebM mimetype 做優化都不告訴別人的八卦？</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[整合 Redmine 和 git]]></title>
    <link href="http://blog.hsatac.net/2011/04/redmine-git-integration/" />
    <updated>2011-04-14T00:00:00+08:00</updated>
    <id>http://blog.hsatac.net/2011/04/redmine-git-integration</id>
    <content type="html"><![CDATA[<p>其實就是[專案設定] > [版本控管] 裡面填 git repo path 而已<br />
不過一直報找不到專案，看了一下 error log  原來是找不到 git 執行檔<br />
解法很簡單，原本 httpd.conf 設定的 ruby 要再包一層去 export path<br />
例如原本你設定的是
<pre lang="bash">
PassengerRuby /usr/local/Cellar/ruby-enterprise-edition/2011.03/bin/ruby
</pre></p>

<p>就開一個  /usr/local/bin/ruby_with_env 的可執行檔<br />
裡面把 export $PATH
<pre lang="bash">
#!/bin/bash
export PATH="/usr/local/bin:/usr/local/sbin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/X11/bin:/opt/local/bin:/usr/local/git/bin:/usr/local/git/bin/:$PATH"
/usr/local/Cellar/ruby-enterprise-edition/2011.03/bin/ruby $*
</pre></p>

<p>再把 httpd.conf 的裡面設定的 ruby 改成
<pre lang="bash">
PassengerRuby /usr/local/bin/ruby_with_env
</pre></p>

<p>大功告成！</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[How to enable php gmp on Mac OS X without macports]]></title>
    <link href="http://blog.hsatac.net/2011/04/how-to-enable-php-gmp-on-mac-os-x/" />
    <updated>2011-04-07T00:00:00+08:00</updated>
    <id>http://blog.hsatac.net/2011/04/how-to-enable-php-gmp-on-mac-os-x</id>
    <content type="html"><![CDATA[<p>If you are using macports, you can easily install the package of &#8220;php-gmp&#8221;.</p>

<p>But if you are a user of homebrew like me, you may need these tips.</p>

<p>First, you have to install gmp via homebrew, but it will give you gmp 5.0.1, which doesn&#8217;t work with PHP 5.3</p>

<p>So you have to modify your Formula, go to /usr/local/Library/Formula/gmp.rb and modify:
<pre lang="ruby">url 'ftp://ftp.gnu.org/gnu/gmp/gmp-5.0.1.tar.bz2'
sha1 '6340edc7ceb95f9015a758c7c0d196eb0f441d49'</pre>
to
<pre lang="ruby">url 'ftp://ftp.gmplib.org/pub/gmp-4.3.2/gmp-4.3.2.tar.bz2'
sha1 'c011e8feaf1bb89158bd55eaabd7ef8fdd101a2c'</pre></p>

<p>Now, you can run <pre lang="bash">brew install gmp</pre> to install gmp.</p>

<p>Next step, download the php source code from php.net, we will need to build a php_gmp.so module from it.</p>

<p>Extract the source code and go to phpsource/ext/gmp/</p>

<p>run
<pre lang="bash">
phpize
./configure
MACOSX_DEPLOYMENT_TARGET=10.6 CFLAGS='-O3 -fno-common -arch i386 -arch x86_64' LDFLAGS='-O3 -arch i386 -arch x86_64' CXXFLAGS='-O3 -fno-common -arch i386 -arch x86_64' make -j6;sudo make install
</pre></p>

<p>And you will get your gmp.so in phpsource/ext/gmp/module/</p>

<p>Copy that to your /usr/lib/php/extensions/no-debug-non-zts-20090626/</p>

<p>And load it in your /private/etc/php.ini</p>

<p>It&#8217;s done!</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[連猴子也會之：在 Mac mini server 上架設 WebDAV git server]]></title>
    <link href="http://blog.hsatac.net/2011/04/%E9%80%A3%E7%8C%B4%E5%AD%90%E4%B9%9F%E6%9C%83%E4%B9%8B%EF%BC%9A%E5%9C%A8-mac-mini-server-%E4%B8%8A%E6%9E%B6%E8%A8%AD-webdav-git-server/" />
    <updated>2011-04-04T00:00:00+08:00</updated>
    <id>http://blog.hsatac.net/2011/04/連猴子也會之：在-mac-mini-server-上架設-webdav-git-server</id>
    <content type="html"><![CDATA[<p>因為我的 mac mini server 不想開著 ssh 一直給人掃，所以想設定 https 的 git server，試了一下真的超簡單的。
<p style="text-align: center;"><a href="http://blog.hsatac.net/images/wp-uploads/2011/04/螢幕快照-2011-04-04-下午1.47.38.png"><img class="aligncenter size-full wp-image-360" title="螢幕快照 2011-04-04 下午1.47.38" src="http://blog.hsatac.net/images/wp-uploads/2011/04/螢幕快照-2011-04-04-下午1.47.38.png" alt="" width="522" height="312" /></a></p>
▲首先打開你的 Server Admin 建立一個新 Site 例如 repo.hsatac.net
<!--more--></p>

<p><p style="text-align: center;"><a href="http://blog.hsatac.net/images/wp-uploads/2011/04/螢幕快照-2011-04-04-下午1.48.24.jpg"><img class="aligncenter size-full wp-image-371" title="螢幕快照 2011-04-04 下午1.48.24" src="http://blog.hsatac.net/images/wp-uploads/2011/04/螢幕快照-2011-04-04-下午1.48.24.jpg" alt="" width="523" height="307" /></a></p>
▲Option 的部份把 WebDAV 打勾，我們要用這個做認證，Folding Listing 也勾起來比較方便。
<p style="text-align: center;"><a href="http://blog.hsatac.net/images/wp-uploads/2011/04/螢幕快照-2011-04-04-下午1.49.02.jpg"><img class="aligncenter size-full wp-image-372" title="螢幕快照 2011-04-04 下午1.49.02" src="http://blog.hsatac.net/images/wp-uploads/2011/04/螢幕快照-2011-04-04-下午1.49.02.jpg" alt="" width="332" height="162" /></a></p>
▲接著建立一個新的 Realm ，範例就用 project.git
<p style="text-align: center;"><a href="http://blog.hsatac.net/images/wp-uploads/2011/04/螢幕快照-2011-04-04-下午1.49.51.jpg"><img class="aligncenter size-full wp-image-373" title="螢幕快照 2011-04-04 下午1.49.51" src="http://blog.hsatac.net/images/wp-uploads/2011/04/螢幕快照-2011-04-04-下午1.49.51.jpg" alt="" width="522" height="288" /></a></p>
▲按+號把你的使用者拖過來，給他權限 Browse and Read/Write WebDAV，</p>

<p>當然如果你要公開這個 repo 給別人讀取，可以把 everyone 的權限設成 Browse and Read
<p style="text-align: center;"><a href="http://blog.hsatac.net/images/wp-uploads/2011/04/螢幕快照-2011-04-04-下午1.50.20.jpg"><img class="aligncenter size-full wp-image-374" title="螢幕快照 2011-04-04 下午1.50.20" src="http://blog.hsatac.net/images/wp-uploads/2011/04/螢幕快照-2011-04-04-下午1.50.20.jpg" alt="" width="521" height="310" /></a></p>
▲最後在 Security 的部份 把 SSL 打勾並選你的憑證</p>

<p>接著就來設定 remote repo 吧！<br />
把你剛剛設定的目錄建立起來
<pre lang="bash">mkdir /Library/WebServer/Documents/repo/project.git
cd /Library/WebServer/Documents/repo/project.git
git init --bare
mv hooks/post-update.sample hooks/post-update
git update-server-info</pre>
記得整個目錄的owner要改回 _www</p>

<p>遠端這樣就設定好啦！<br />
接著本地端的部份：</p>

<p>因為我們是走 https ，如果你的憑證是自簽的話，請先跟我這樣做：
<pre lang="bash">git config --global http.sslVerify false</pre>
接著一樣三步驟：
<pre lang="bash">git init
git add .
git commit -m "first commit"
git remote add origin https://repo.hsatac.net/project.git/
git push origin master --force -v</pre>
最後編輯 .git/config<br />
加上
<pre lang="bash">[branch "master"]
	 remote = origin
	 merge = refs/heads/master</pre></p>

<p>以上，就大功告成啦！</p>
]]></content>
  </entry>
  
</feed>

