My First Contribution to Nginx

nginx conf

因為工作上的需要,所以其實我還蠻常會編輯 nginx configuration file 的,理所當然的編輯器是用 vim,然後就會對 nginx 設定檔的支援有意見,一般人用的 nginx 設定檔的 vim script 其實是 nginx repository 的 contrib 目錄裡面的那份,這份 vim script 其實本來也是獨立的,不過原作者好像把他捐進去 nginx 裡面,之後就一直都在裡面了,也因此之後更新就很不頻繁。

然後因為檔案都放在 nginx repository 裡面,Vim 要使用其實不太方便,所以 Github 上還看的到不少人單獨抽出來,我一開始也是 forkmosky的來用,後來就直接在自己的 repository上面修改了,改一陣子之後就開始想要推回 upstream,也就是 nginx 的程式庫,然後就開始了這段協工旅程(?)。

要發修改上 upstream,第一步自然是看一下如何貢獻,節錄這邊幾個重點:

  1. nginx-devel這個 mailing list 做討論
  2. 發 patch 前有一些注意事項,不過我改 vim script 比較沒關係
  3. Patch 也是用 email 發到 nginx-devel,有範例
  4. 推薦用patchbomb
  5. 要先簽CLA(不過目前這條已經不見了,改成最後說發 patch 等於同意用他們專案的 LCIENSE)

總之我就照這份,先去訂閱了 nginx-devel 觀察一陣子,然後就直接把我的修改整個丟上去了,一開始是直接用 Gmail 發,把 patch 檔內容直接複製貼過去,產生 patch 檔的方法是:

hg export > something.patch

hg export會直接輸出最後一個 commit 的 patch 內容到 STDOUT,然後就直接用 Gmail 發過去,結果 review 的Maxim Dounin說他沒辦法 apply patch,可能是因為我的 mail client 的關係,建議我用patchbomb發,所以就研究搜尋了一下,發現他是直接發 email 的機制,所以要把帳號密碼都寫到設定內,找了一篇 Gmail 的設定範例,搭配 Google account 的應用程式密碼,設定範例如下:

[extensions]
hgext.patchbomb =

[email]
from=othree <othree@gmail.com>
to=nginx-devel@nginx.org
cc=othree@gmail.com
method=smtp

[smtp]
host=smtp.gmail.com
port=587
username=othree@gmail.com
password=[gmail_password]
tls=True

把這些資訊填入.hg/hgrc這個檔案內,然後就可以用hg email -o --test來測試看看,這個指令會把完整的原始信件內容,包括 header 等都顯示出來(丟到 STDOUT),如果正式要發就把--test拿掉就好了。

確認一切沒問題後,我就改用 patchbomb 發 patch 到 nginx-devel 了,結果還是被拒絕了,問題主要是這個 patch 一次修改太多,理想上應該是不同目的的修改放到不同 patch 內,當然這和我一開始的預想不一樣就是了,我一開始的想法是因為 contrib 這邊的東西,相對於 nginx 本體的原始碼來說比較次要,所以盡量減少 commit 數,其實如果我有先去問過應該是可以少繞這段路,總之,為了一個一個修改送出,我又開了一個 github repository,叫做nginx-contrib-vim-patch,想要慢慢把我的 nginx-contrib-vim 內的更動搬過去,接著開始的,就是漫長的 review 和溝通了。

其實我完全沒想到 Maxim Dounin 會這麼認真的 review,不止會看我這樣改是要達到什麼目的,還有認真測試,結果被抓出一堆問題,雖然都是奇妙的 conf 寫法,合語法,但是應該不會有人這樣寫的 case,這些 case 我也開始慢慢收集到 github 上的nginx-conf-test,方便之後測試用,總之來回許久,終於有一部分比較簡單的東西先進去 nginx repository 了,然後我發現外部貢獻者都會在change log那邊被感謝,我貢獻進去的目前應該都在 1.11.11 那版,其實只有把新的 directive 補上(core modules, 3rd party modules)和幾個 protocol 參數的 highlight,至於其他的修改還進不去,目前看起來會是一場長期抗戰,主要是因為 reviewer 對於期望的目標和我不一樣,目前大概會維持兩個版本吧,一邊弄自己希望的,一邊抽東西送回去 upstream,不得不說主事者控制太緊會讓貢獻者動力被削減不少。

貢獻 nginx 的過程讓我體會到以前的開源協做的模式(應該是吧?),用 mailing list 溝通,發 Patch、code review、做討論,這些點來看,nginx 的流程其實是非常老派,和現在用 Github 做溝通、協做 的流程差很大,門檻也高不少,當然這不一定是壞事,還是要看專案性質,在 Github 這類平台上做這些協做流程的話,門檻降低了,其實可能隨之而來的問題就是太多人進來造成貢獻品質落差很大,反而會吃掉主力人員的時間,剛好今天也看到知乎上有一篇「維護一個大型開源專案是怎樣的體驗?」,裡面就有提到 VSCode 的狀況,變成還需要排人專門處理 issue 和 PR,感覺就很可怕。

順帶一題,nginx 的固定貢獻者當中不少中國人啊。


Docker 雜談

最近使用的一些感想和疑問

  • --name自動會變 network 內的 hostname,蠻方便
  • Image build 失敗,還是會產生一個東西在那邊,要 rm 掉才能重新 build...
  • Service 還不支援 update 修改 network
  • DB container 的資料要開 volume 掛比較保險(免得不小心砍到 container)
  • 在多個 node 上開 replica,掛 volume 的話都是在該 node 上找,目前似乎沒有透過網路共享 volume container 這種事
  • 很多服務的官方 docker 都是用環境變數做設定,不知道是不是本來就有的慣例
  • 一直更新 registry 上的 image 好像會越來越多垃圾,不知道是不是有清理機制
  • 整體而言,我覺得 docker service 介面是個很容易讓 fat finger 造成服務爆炸設計,不過架構規劃的好的話,應該不會太難修復就是

Ubuntu 14.04 與 MovableType 4.x

前一篇文章提到我為 SSL 安全性升級到 Ubuntu 14.04,其實升級之後遇到一些 MovableType 的相容性問題,Ubuntu 在 12.04 的時候還是用 Perl 5.14,不過到 14.04 時,Perl 升級到 5.18 了,順便提一下現在最新的穩定版是 5.20,不過 5.18 和 5.20 是同時都有在維護的。

然後我的 MovableType 是用很久以前的 4.38,用新的 Perl 會跑不起來,不過我也不太想升級,一來是 License 問題,二來是新的 MT 一個很大的架構改變是他變成是多 blog 系統,我也不太喜歡這點。總之剩下的方法就是想辦法修 bug,或是用舊的 Perl 跑,顯然後者容易許多,然後我也找到 gugod 開發的perlbrew這工具,類似於Ruby 的RVM,c9s 也有寫一篇文章介紹

比較有趣的是我用了 perlbrew 安裝好 Perl 5.14 後,用which perl找到 Perl 5.14 執行檔位置然後手動修改 mt.cgi 等檔案,用 mt-check 檢查發現還缺 DBI 的套件,就用升級前就已經裝好的 cpanminus 裝了,不過怎麼裝都顯示正常但是 MT 就是一直抓不到,看了一下 cpanm 檔案原始碼才發現它用的 perl 是:

#!/usr/bin/perl

心想 gugod 怎麼可能不處理這個問題,於是搜尋一下發現可以用perlbrew 安裝 cpanm

perlbrew install-cpanm

看了安裝出來的 cpanm 用的 perl 來源是不一樣的:

#!/usr/bin/env perl

這樣用 cpanm 裝的 Perl 套件總算可以用了,之後還有一個 5.14.2 和 5.14.4 的差異造成的錯誤,就照網路上找到的文章修正了。


[

最近因為shellshock的關係,跑去看了/bin/下面的東西,結果突然發現有個執行檔叫做[

ls /bin/

執行了也完全沒反應,結果和同事討論就上去 stack overflow 來問問看,然後馬上就被回說看看man [。想不到,原來 shell script 裡面的 if else condition 的[ ],其實就是這個執行檔啊,以前一直以為是個語法的 syntax...


mozjpeg 2.1

Mozilla 最近發佈了mozjpeg2.1,同時還有一篇用 mozjpeg 產生高效率的 JPEG教大家使用裡面的工具,所以我之前誤會以為現在只有 c lib 可以用,這篇文章有一些範例指令讓大家可以把cjpeg把圖片重新壓縮,小缺憾是安裝講的比較不清楚,所以我另外測試過,提供一下 Mac OSX 的指令:

cd mozjpeg
autoreconf -fiv
mkdir build && cd build
sh ../configure
make
sudo make install

關鍵的就是BUILDING.txt沒說build目錄是要自己建立的,不過實際測試的效果要等週一才能測試看看,目前只有編譯過確定有指令工具可以用而已。

另外一個比較容易漏掉的是要編譯需要NASM, homebrew 可以直接brew install nasm


OSX 裝 ruby 1.9.3p392 編譯問題

最近因故要在 Mac 上重新建立工作環境,結果在裝 ruby 時遇到 compile error,看起來也不是今天才有的問題,狀況是 clang 4.1 之後才開始有的,而 OSX 10.9 要用的 XCode 5.0.1 已經是 clang 5.0 了,所以不避開這個問題會無法在新的 OSX 上裝 Ruby,包括用其他 Ruby 管理工具也是一樣,像我其實就是用 rvm 要裝,還好有解法:

CFLAGS=-Wno-error=shorten-64-to-32 rvm install ruby-1.9.3-p392

fasd, 命令列加速工具

以前曾經介紹過autojump這個很好用的快速切換目錄的指令,後來大貓跟我說有個叫z的,一樣用途,原理也差不多,不過 z 的位置比較好按些,最近在看Vim Scripts時,意外發現到有個fasd,也是一樣的原理,不過他的功能比較強大,配合一些 alias 就可以做到和z或是v一樣的功能,作者對相關的領域很熟悉,對於常用 shell 的整合很好,像是 zsh 和 bash 的指令補完就都有支援,目前正在改用他,Mac 安裝很方便:

brew install fasd

然後在.bashrc或是.zshrc加上

eval "$(fasd --init auto)"

就可以了,其他環境有包好的就比較少了,可以看看他的 Wiki:Installing via Package Managers,其他的環境我測試過 Ubuntu 編譯安裝都很順利,基本上只是拷拷檔案而已。


Build v8

平常是使用 Google V8 引擎的 command line 來做自己工作機的 js console,最主要的用途是跑 jslint,不過這需要自己來編譯,以前是用 scons 來編譯,剛剛想要編譯新版發現 Google 又換了自動化工具,從scons換成gyp,安裝流程其實比較簡單,先安裝好 svn,然後執行:

make dependencies
make console=readline native

產生的 d8 執行檔會在 out/native/ 下面,官方說明有提到可以用 clang 編譯,不過我嘗試後會有錯誤,還在看要怎樣處理。


automjump

今天發現的有趣的命令列工具autojump,它會記錄你常用的目錄位置,然後之後就可以用簡單的關鍵字跳到路徑符合關鍵字,又最常用的目錄,以我為例,我最近常常會跑到某個位置的 vim-plugins 目錄,然後我又沒有其它目錄名稱和 plugin 相似,那不論我在哪,我都可以執行下面的指令跳到 vim-plugins:

j plugin

我目前使用上是都沒什麼大問題,不過hlb說他的 vim 檔名自動完成會爛掉,可能要在研究看看問題在哪了。


彩色 man page

忘了哪裡看到的設定了,用的是 zsh

# colorful man page
export PAGER="`which less` -s"
export BROWSER="$PAGER"
export LESS_TERMCAP_mb=$'\E[38;5;167m'
export LESS_TERMCAP_md=$'\E[38;5;39m'
export LESS_TERMCAP_me=$'\E[38;5;231m'
export LESS_TERMCAP_se=$'\E[38;5;231m'
export LESS_TERMCAP_so=$'\E[38;5;167m'
export LESS_TERMCAP_ue=$'\E[38;5;231m'
export LESS_TERMCAP_us=$'\E[38;5;167m'

效果預覽:

colorful man page


此類別所有文章