遇到鎖右鍵的網站時, 複製文字變得有點麻煩, 要檢視原始碼再去掉 tag。剛從 Shakalaca 那看到《Become a Javascript Console Power-User》, 學到不錯的方式, 比較省事地取出文字:
- 按 F12 開 Chrome console
- 點 Elements 選放大鏡
- 選取要的段落 (html node)
- 在 console 裡打 copy($0.innerText)
這樣就複製好了, 只剩貼到文字編輯器裡去掉不要的部份即可。
遇到鎖右鍵的網站時, 複製文字變得有點麻煩, 要檢視原始碼再去掉 tag。剛從 Shakalaca 那看到《Become a Javascript Console Power-User》, 學到不錯的方式, 比較省事地取出文字:
這樣就複製好了, 只剩貼到文字編輯器裡去掉不要的部份即可。
直到看了 Dan Saks 的 const T vs T const, 才(比較)明白 C 的型別宣告, 知道 int const *a 和 int * const a 的差別。原本雖然知道 int (*f[10])(int )、int (*f)(int) 和 int *f(int) 的差別, 但沒有很清楚細部原因, 看了這篇後才懂得更徹底。
C 的宣告分幾個部份, 以 static unsigned long int *x[N] 來說, *x[N] 是 declarator, 剩下的是 declaration specifier。declarator 的部份用運算子優先順序來解讀, 語意清楚許多。即 () 最優先, 其次為 [], 再來為 *。所以:
令人混淆的部份在於, declaration specifier 的順序其實沒有影響。所以, static unsigned int n 和 int unsigned static n 是一樣的。再加上 const 和 volatile 不同於其它 declaration specifier, 它們可以同時寫在 declarator, 於是產生不易理解的結果。
我還在參透 volatile 的效果, 這裡先以 const 為例:
簡單的判別方式是以 * 為分界點, 由右往左看, 包含 * 的右邊是 declarator, 表示 declarator 的型別, 所以這裡有 const 表示是唯讀的指標; * 的左邊是 declaration specifier, 這裡有 const 表示指到的型別為唯讀。附帶一提, 用英文來解讀的話似乎比較清楚, 不知是自己受程式語言的影響, 還是英文天性比較有邏輯一點, 總覺得用英文思考比較有利於理解數學、程式之類的事。
比方說:
善用 const 產生 immutable 的效果可以減少 bug、易於維護, 學好這些觀念滿實用的。作者建議將 * 貼近 declarator 並且將 const 寫在最右側, 避免誤會。 * 貼近 declarator 是因為 compiler 本來就是這麼解讀的, 將 * 放在 int 旁會不易分辨 declaration specifier 和 declarator。而將 const 寫在最右側則可避免誤會, 像文中的例子:
typedef void *VP; const VP vectorTable[]
原以為表示 vectorTable 的內容都為 const, 但 compiler 會解讀成
VP const vectorTable[]; // 等同於 void * const vectorTable[];
變成 vectorTable 是一個陣列, 每一個元素是唯讀的指標, 指標指向的型別為 void (即沒指定特定型別)。若希望宣告 vectorTable 的指標不為唯讀, 是指到的型別唯讀, 有兩種作法:
// 1. void const * vectorTable[]; // 2. typedef void const *VCP; VCP vectorTable[];
寫完這篇後讓我想到 int **p 的情況, * 和 * 之間可以插三個 const, 這才體會到作者強調的觀念:
Although C and C++ read mostly from top-to-bottom and left-to-right, pointer declarations read, in a sense, backward.
用這種方式解讀 int const * const * const p 的確比較直覺, p is a read-only pointer to a read-only pointer to a read-only int。
ps. const-correctness 提到更完整的 const 語意, 包含函式的部份。
換掉動態連結的函式庫有不少用途, 比方說像 Scott 提的「用來驗證是否執行到特定函式」, 或如 jserv 提的「在沒有原始碼的情況下修補執行檔的行為」。最近又看到這個東西, 記一下筆記以免忘了。
來看程式碼和執行效果。
mylib.c
#include <stddef.h> #include <stdio.h> int putchar(int c) { printf("call putchar()\n"); return c; } void *memset(void *s, int c, size_t n) { printf("call memset()\n"); return s; }
main.c
#include <string.h> #include <stdio.h> int main(void) { char s[10]; memset(s, 0, 0); putchar('X'); putchar('\n'); return 0; }
執行結果
$ gcc -Wall -fpic -shared -o libmylib.so mylib.c $ gcc -o main main.c # 沒用 LD_PRELOAD 的結果 $ ./main X # 用 LD_PRELOAD 後的結果, 記得加 "./", 不然會找不到 libmylib.so $ LD_PRELOAD=./libmylib.so ./main call putchar() call putchar() $ strings main | grep memset
可以看出 putchar 有被換成自己編的版本, 但 memset 沒有。用 strings 查看 binary 檔 main 會發覺並沒有呼叫 memset 的跡象。猜測是 compiler 發覺 memset 實際上沒任何作用, 所以沒呼叫。
修改 main.c, 將 memset(s, 0, 0) 換成 memset(s, 0, 1) 再來看看:
$ gcc -o main main.c $ strings main | grep memset memset $ LD_PRELOAD=./libmylib.so ./main call memset() call putchar() call putchar()
結果顯示有換到 memset, 表示之前是完全沒呼叫 memset, 才會以為沒換到。printf 也是如此, 只輸出字串時, 不會呼叫 printf, 而是用 puts。
參考資料: 《Modifying a Dynamic Library Without Changing the Source Code | Linux Journal》
偶然看到 PythonWebkit 這個專案, 作者花了兩週左右的時間寫好 WebKit 的 python 介面, 於是操作 DOM 不再是 javascript 的專利, 透過 PythonWebkit 就能用 python 操作 DOM。作者自稱除一些小功能外, 這個專案已到可用的階段:
The current status is that the SVG 2D Canvas element is not available, and CSS Styles have to be modified through the style.setProperty function (rather than being accessible as python properties). Other than these gotchas, the Python Webkit bindings are in a useable state, providing full W3C compliant access to the full set of DOM functionality (except SVG Canvas) as provided by Webkit, and ordinarily only accessible via javascript.
不過相關文件超少, 花了些時間才裝成功, 也增加了一些編原始碼的功力。
WebKit 的歷史很有意思, 有興趣的人自行參照連結。在 Linux 上目前有兩種 port, 一個是用 GTK+ 實作的WebKitGTK+, 另一個是 QT 的實作版本。
PyWebKitGtk 是另外一個基於 WebKitGTK+ 的專案, 透過 WebKit 提供的 gobject binding 提供 python 介面, 但沒有提供直接操作 DOM 的功能。雖然有些補救方案, PythonWebkit 的作者覺得直接改出 python 介面比較省事, 效率也較好, 該頁有寫詳細的設計考量。所以, PythonWebkit 是以 WebKitGTK+ 為底, 修改部份內容直接提供 python 的 DOM API。
剛開始作者用 PyWebKitGtk 的 python module "webkit", 藉此省掉寫 python module 的步驟, 然後加上 patch 讓 webkit (python module) 能取出 DOM。也就是說, PythonWebkit 依賴 PyWebKitGtk; PyWebKitGtk 依賴 WebKitGTK+; WebKitGTK+ 是 WebKit 在 Linux 下的實作版本之一。
後來作者自己重寫一個 python module "pywebkitgtk", 就不用再裝 PyWebKitGtk 了。網路上找 PythonWebkit 的文件, 有部份會提到 PyWebKitGtk, 但現在已用不到它了。弄清楚這堆名稱差不多的專案, 花了我一些時間 ..., 搞清楚後也滿有成就感的。
上面是簡化的說法, 實際上 PythonWebkit 不是直接依賴 WebKitGTK+, 也可以改用基於 DirectFB 的 PyWebkitDFB。由於這還在實驗階段, 我就沒試了。
主要參考 PythonWebkit 的說明, 另外需要參照 WebKitGTK+ 的安裝說明, 了解它用到的套件。在 Ubuntu 下的安裝步驟如下:
1. 升級到 11.04, 11.04 的 glib 版本才夠新 (>= 2.27.4)
不然會出現
configure: error: You need the GLib dev tools in your path
2. 安裝編譯 WebKitGTK+ 需要的套件
注意: 最後三個指令不能用 aptitude, 只有用 apt-get 才能確保移除後仍保有需要的設定
$ apt-get install python-dev python-ply $ apt-get build-essential $ apt-get build-dep libwebkit-1.0-2 $ apt-get install libwebkit-1.0-2 $ apt-get remove libwebkit-1.0-2
在 Ubuntu 下自己編原始碼時, 似乎滿常用這招的, 透過原有的套件管理系統裝好相依的套件、取得需要的 header 等資源, 藉此減少手動操作部份。
3. 取得 PythonWebkit 原始碼, 這步會花很長的時間, 好像會到一小時吧
$ git clone git://git.savannah.gnu.org/pythonwebkit.git
4. 切換到 branch python_codegen
$ git checkout python_codegen
注意: 千萬不要加 "-b", 我不熟 git 參數, 誤加了 -b, 變成開一個新的 local branch 叫 python_codegen, 而不是取出遠端的 branch python_codegen。git 指令請參考《Git 版本控制系統(2) 開 branch 分支和操作遠端 repo.》。
有取對 branch 的話, grep 整個目錄應該會找到 pywebkitgtk 相關檔案; 反之則否。pywebkitgtk 是 PythonWebkit 產生的 python module, 作用和 PyWebKitGtk 的 webkit 差不多, 不過多了取得 DOM 的方法 (web view 的 GetDomDocument())。
5. 開始編譯
$ mkdir build $ cd build $ ../autogen.sh $ make
我的電腦是三年前買的, 在 VM 裡用雙 CPU 編的話 (配合 make -j 2), 大概四十多分鐘可編完。
執行 autogen.sh 時, 若發現缺了東西, 可用 aptitude search 加關鍵字, 或 apt-file search xxx.h 查看看放在那個套件, 通常是要裝一些 X-dev 的 package。印象中我好像有少了 pygtk。有問題時, 記得用 dpkg -l 和 WebKitGTK+ 的 Dependencies 對一下, 看有沒有少裝什麼。然後再重跑 autogen.sh。
6. 檢查結果
編好的東西放在 .libs/ 下, 不知是不是某種慣例。上網查 make install 的討論, 似乎沒有明確的方法可以找到會裝那些東西進系統。幸運的話, 可以用 checkinstall 裝成 deb 檔, 就能用 dpkg -L 查裝了什麼, 也能用 dpkg -r 移除。不過我用 checkinstall 的結果, 似乎比直接 make install 多裝了不少東西, 最後直接用 make install。
回到正題, 先切到 .libs 下看編完的東西是否可用。.libs/ 下應該要看到 libwebkit 的 so 檔, 還有 pywebkitgtk.so。接著在 .libs/ 目錄下執行 ipython, 依序打入:
import gtk import pywebkitgtk url = "http://www.gnu.org/software/pythonwebkit" wv = pywebkitgtk.WebView(1024,768, url=url) doc = wv.GetDomDocument() ns = doc.getElementsByTagName('h2') ns.length # 9 ns.item(0).innerHTML # 'Why is this important - why is it a "big deal"?'
注意, 上述程式要在 X Window 下執行。import gtk 後, 在產生 WebView 物件時會跳出視窗。若沒有 import gtk 的話, 不會有任何錯誤訊息, 但取得的 doc 裡面卻沒任何東西, ns.length 會是 0。
7. 安裝到系統
$ sudo make install
然後檢查 /usr/local/lib 是否有在 ldconfig 路徑中:
$ grep -R "/usr/local/lib" /etc/ld.so.conf.d/
若沒有的話, 在 /etc/ld.so.conf.d/ 下新增一個檔案:
$ sudo echo "/usr/local/lib" > /etc/ld.so.conf.d/webkit.conf
最後是更新 ldconfig 的 cache:
$ sudo ldconfig
不確定原本 /etc/ld.so.conf.d/ 下就有 /usr/local/lib 的情況是否要執行 ldconfig, 好像要執行才會 ok, 但看文件說, 一般 make install 時應該會自動執行這個動作。
之後就能在任何地方直接 import pywebkitgtk 啦。
附上一個小例子: 取出 TechCrunch 文章有多少人按 Facebook 的 like:
import os import gtk import pywebkitgtk wv = pywebkitgtk.WebView(10, 10, url='http://techcrunch.com/2011/09/25/clinging-to-friction-some-thoughts-on-facebooks-f8/') os.sleep(10) # Wait Facebook plugin to be loaded. dom = wv.GetDomDocument() iframes = dom.getElementsByClassName('fb_ltr') for i in range(iframes.length): e = iframes.item(i) ns = e.contentDocument.getElementsByClassName('connect_widget_button_count_count') if ns.length > 0: print ns.item(0).firstChild.nodeValue # Count of "FB like"
TechCrunch 的推文數大多是用 AJAX 載入到 iframe 裡, 用普通的方法無法抓到內容。上面的作法相當粗糙, 就將就用啦, 這不是本篇的重點。
產生 wv 後會看到 console 出現一堆訊息, 大概是載入頁面後, 以及執行完後續 AJAX 時產生的。之後再來看看這些訊息是否有害。
PythonWebkit 沒有多提相關 API, 因為作者為了方便大家查文件, 讓 PythonWebkit 和原本的 DOM API 100% 相容 (目前只有 CSS 部份有一點不同), 所以, 直接學 DOM 就可以了。配合 ipython 直接操作, 還滿容易試的。
1. configure: error: You need the GLib dev tools in your path
參考 這篇, 要用新版 glib, Ubuntu 要到 11.04 才符合。我鐵齒的從 10.04 一路試, 直到 11.04 才真的 ok。不過 libsoup 用 2.24 也 OK, 不需要像 PythonWebkit 說要用最新版才行(2.29.90), 不確定之後會有什麼問題。
2. 編譯時出現 "error: webkitmarshal.h: No such file or directory"
參照這篇, 執行
$ touch ./Source/WebKit/gtk/webkitmarshal.list
然後重跑 make。
3. 無法 import pywebkitgtk / 沒有編出 pywebkitgtk.so
記得在取得 repository 後要先執行 "git checkout pyhton_codegen" 才執行 ../autogen.sh, 千萬不要寫成 "git checkout -b pyhton_codegen"
4. import pywebkitgtk 時說找不到 libwebkitgtk
In [1]: import pywebkitgtk --------------------------------------------------------------------------- ImportError Traceback (most recent call last) /usr/local/lib/<ipython-input-1-8dab5af5d34b> in <module>() ----> 1 import pywebkitgtk ImportError: libwebkitgtk-python-1.0.so.0: cannot open shared object file: No such file or directory
先用 ldd 檢查路徑是否確實有問題:
$ ldd /usr/local/lib/python2.7/dist-packages/pywebkitgtk.so | grep libwebkitgtk libwebkitgtk-python-1.0.so.0 => not found
出現 "not found" 表示 pywebkitgtk.so 找不到 libwebkitgtk-python-1.0.so.0。接著檢查 /etc/ld.so.conf.d/* 有沒有含 /usr/local/lib (當然, 要先確定你的 libwebkit-python-1.0.so 有裝到那)
將 /usr/local/lib 加到 ldconfig 的路徑後, 執行 sudo ldconfig。
另外看到有人提到在編譯前這麼做:
$ export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig
不過我試了沒成功, 之後有空再來看 pkgconfig 是什麼。
有了 pythonwebkit 後, 可以用 python 直接存取 DOM。於是得自己學一下 DOM 的操作方式, 不能再依賴 jQuery 啦。
花個半小時邊看邊操作 《HTML DOM Tutorial》, 很快就有個基本概念了。記一下自己不熟的部份:
有時用 putty 連到 server, 打 vi 後會停一兩秒才進去。有時在 screen 下甚至會停住不動。參考這篇的說法, 用 vi -X 不要連線到 X Server 就 ok 了。
會有這樣的問題, 是因為我用到 gnome 版的 vim (vim.gnome):
$ which vi /usr/bin/vi $ ll /usr/bin/vi lrwxrwxrwx 1 root root 20 2010-05-12 12:17 /usr/bin/vi -> /etc/alternatives/vi* $ ll /etc/alternatives/vi lrwxrwxrwx 1 root root 18 2010-08-06 13:58 /etc/alternatives/vi -> /usr/bin/vim.gnome* $ ll /usr/bin/vim.gnome -rwxr-xr-x 1 root root 2144568 2009-01-08 11:03 /usr/bin/vim.gnome*
若用 vim.tiny 或 vim.basic, 不加 -X 也不會停一會兒。
相關除錯指令:
記一下個人裝 Ubuntu 後, 會做的基本設定。
若需要裝 java, 另外需做:
若是用 Parallel 的話,裝完 Parallel 附的 Ubuntu 後要作的事:
日後想到什麼再補。
之前看 Ubuntu 的 fstab 改用 UUID 覺得很納悶, 為啥要在 /dev/disk/by-uuid/ 下建 soft link 再指到 /dev/sdXN (X 是 abcd, N 是 1-8), 然後在 fstab 裡用 UUID 而不用 /dev/sdXN。
今天用 VirtualBox 移除硬碟後才發覺它的好處: 加裝或移除硬碟後, 雖然 /dev/sdXN 的 X 會變 (如移掉第二顆硬碟, /dev/sdc3 會變 /dev/sdb3), UUID 卻不會變。所以若 /etc/fstab 用 UUID 來掛載 partition, 可以直接開機, 而省掉進單人模式改 /etc/fstab 的步驟。
討論 coding style 時, 這個常會戰到爆。記一下在多人一起開發一陣子軟體後的心得。
我後來覺得 space 比較方便, 因為可確保任何地方看到的畫面一致, 且不需另外設定。支援 tab 的人認為只需要一次設定就可以了, 這樣可保留彈性。困難的地方在於有太多地方可能會看到程式碼: IDE、editor、VCS log、issue tracking、e-mail、其它可能的 web-based 工具 (如 code review)。而有些地方無法提供客制化設定 tab 寬度 (如 e-mail)。
以我自己用 Java 來說, 平時可能用 Eclipse, 特定需求時用 vim, 偶而要用 hgtk 看別人的 commit (一些程式碼的 diff), 或用 hg blame 看修改記錄 (輸出到 console 或用 hgtk 看), 偶而寄 code diff 給別人討論。在這些過程中, 會發覺 tab 實在是不太方便。
至於 space 的缺點: 一但定了就很難改, 實務上不是問題, 各個語言都有標準規範 (大概都是四個空白), 照著公定規範做就是了。若不幸地原本已有一大堆其它長度, 讀個一陣也會習慣, 應該會比在不同地方, 縮排亂掉來得好。
去年的隨手心得, 記在這備忘。主要是參考《MySQL vs PostgreSQL - WikiVS》 2010-09 的版本, 後來情況應該也有些變化。另外, 很多東西還是要自己測過才準, 後來和一些很熟 DB 的前輩聊, 發覺實際情況還是和看到的有些出入。需求不同, 又有太多細節可以調整了。
後來覺得選用 MySQL 的好處是:
fcamel 2010-09-01 19:54:43 MySQL vs. PostgreSQL, 有這種對照文真不錯, 書上有看過的相關觀念可以重新消化一次, 之前沒看過的....在這也有看沒感覺 MySQL vs PostgreSQL - WikiVS MySQL vs PostgreSQLFrom WikiVS, the open comparison websiteJump to: navigation, search MySQL Postgr 發表回應 1 fcamel 2010-09-01 19:55:43 PostgreSQL 只有一個 engine, 一般來說在大量同時寫入下會比 MySQL 搭各種 engine 快 2 fcamel 2010-09-01 19:56:36 PostgreSQL 比較穩, RDBMS 功能較齊全, 這點在 stackoverflow 上可找出一卡車支持者。也可找出一卡車 MySQL 使用者說他們遇到 DB 炸了多少次 3 fcamel 2010-09-01 19:57:24 MySQL + MyISAM 有無敵快的 count, 因為它沒 MVCC, 可以視情況直接 count index 而不用取 data rows。又因為沒 MVCC, 可以安心地 cache count 4 fcamel 2010-09-01 19:58:58 8.x 的 PostgreSQL 沒有 Insert Ignore / Replace 5 fcamel 2010-09-01 20:00:31 MySQL + MyISAM 在 read-only 或低頻率寫入的情況下是超級快, 因為它沒 constraint, 沒 MVCC。無賴戰法: 我就什麼功能都沒有, 但是只讀不寫的話, 我超快的哦!! 6 fcamel 2010-09-01 20:00:49 剛好我們現在正好只需要這種無賴戰法 XD 7 fcamel 2010-09-01 20:06:12 mysql 內建 replication 機制, 效率比 PostgreSQL 好 (?) 8 fcamel 2010-09-01 20:07:41 Ubuntu 8.04 的 mysql 版本有點舊, 只到 5.0.51a, 之後有幾版大幅提昇速度, 5.1 又有多 sharding 的樣子。 9 fcamel 2010-09-01 20:10:56 PostgrelSQL 有 Bitmap Indexes, 可以合併兩個以上的 indexes, 之後來看看這是啥。一直很好奇怎麼做才能同時用兩個 indexes 10 fcamel 2010-09-01 20:13:45 MySQL 有 covering index, 而 PostgrelSQL 沒有, 令我滿意外的, 原以為 index 那區 MySQL 會兵敗如山倒 11 fcamel 2010-09-01 20:15:14 PostgreSQL 支援 expression indexes, 意思是也可以查 "%keyword%" 嗎? 太神奇了! 之後來查查這是啥 12 fcamel 2010-09-01 20:19:32 這個有意思: "In PostgreSQL there is no built-in mechanism for limiting database size. This is the main reason why the most of the web hosting companies are using MySQL. Also, PostgreSQL doesn't have scheduled procedures. " 13 fcamel 2010-09-01 20:20:32 結果 PostgreSQL 無法流行的主因是沒做這種看似不重要的功能嗎? XD 14 fcamel 2010-09-01 20:23:40 天啊...., 難怪有人提到他比較喜歡 PostgreSQL 的 license, MySQL client library 是 GPL 非 LGPL!! 若沒和 Sun (現在是 Oracle?) 買授權, 就得 open source, 太可怕了... 15 fcamel 2010-09-01 20:30:10 看完兩者的討論後還真想用 PostgreSQL 啊, 考量現況還是繼續用 MySQL 比較務實 Orz 16 fcamel 2010-09-01 20:41:29 stackoverflow 有人提到用 PostgreSQL 加 column 似乎不用鎖住 table, 他們之前用 mysql + replication 的結果, 就不敢加 column, 只好另開 table 用 join 取資料 17 榮尼王 2010-09-01 20:53:54 mysql 加上 master-master 架構的話,alter table 就隨便了啊 18 fcamel 2010-09-01 21:04:56 soga, 還沒看深, 果然各種問題都有一定的配套解法, 謝啦。 回應
這對於新手來說應該很有幫助吧
在 [mysqld] 下的相關設定:
character-set-server=utf8 collation-server=utf8_general_ci init-connect='SET NAMES utf8'
MySQL 的設定檔位置不太好找, 細節參考《fcamel 技術隨手記: 更改 mysql conf 的注意事項》。
一開始用 MySQL 的 MyISAM 時, 發覺有語法可以事先載入整個 index, 就以為大部份 server 應該有提供這功能。不過後來發覺 InnoDB 沒有, 所以要自己下 SELECT 掃一次 table, 讓 MySQL 自動觸發 cache 機制。後來用 Solr, 查了一陣子, 似乎也沒有這種機制。大概設計 server 的人覺得另外設計語法會增加維護成本, 不如讓大家自己查詢全部要用的資料, 讓 server 自己管好 cache 比較實際吧。
MyISAM 的 index 會暫存到 key cache 裡, 若想預先載入整個 table 的 indexes 到 key cache 裡, 可以用 LOAD INDEX INTO CACHE。但若要 flush key cache 的話, 並沒有像 flush query cache 那樣有 RESET QUERY CACHE 的語法。替代作法是, 改變 key cache 的大小或 block size, MySQL 就會重設 key cache。
ReviewBoard 沒有提供批次刪掉的介面, 測試期間產生一堆 request, 懶得用手一個個刪, 想說用 API 來刪。
使用 ReviewBoard 的 web api, 需要在連線中的 http header 加上 cookie 資訊用作身份認證。用 python 的 httplib2 做這事也不會太麻煩, 不過若能用 command line 解決, 會更簡單一些。後來我用 curl 做這事, 順便熟悉一下它的功能, 常看文件用 curl 示範 API 用法。
參考《Use CURL to Login to Websites with a Script》的教學, 學會 curl 登入網頁的用法。依我的需求消化後的步驟如下:
備註: 砍 request 要用 http://myhost/api/json/reviewrequests/$i/delete/, 但要有 admin 權限
使用 apache2 + mod_wsgi 的作法架 ReviewBoard 的話, relative path 有 bug, 無法將 ReviewBoard 架在 http://.../reviews/ 這樣的位置。網路上搜搜看到也有人提到同樣的問題。自己試著硬解了一陣子, 沒有很乾淨又一致正確的結果。後來想說, 乾脆在同一台機器的 apache 裡跑聽兩個 port 好了, 這樣就能在用專屬非 80 的 port 來架 ReviewBoard。
查了一下, 架法還滿簡單的: 見 VirtualHost Examples, 另外 CommonMisconfigurations - Httpd Wiki 也滿有幫助的。使用多個 port 時, 記得要加 listen。Ubuntu 的話是加在 /etc/apache2/ports.conf 裡, 它會被 /etc/apache2/apache2.conf include 進去。
Fedora 似乎因為執行檔撞名,而沒有提供 id-utils 的套件 ,但這是使用 gj 的必要套件,只好自己編。從官網抓好 tarball ,解開來編譯 (./configure && make)就是了。 但編譯後會遇到錯誤: ./stdio.h:10...