偶爾你會需要刪除特定目錄下的空目錄,一個一個去找顯然不太聰明而且相當費時。

可以簡單的利用  find 來找,兩個參數可用,分別是 -depth 與 -empty。另外你可以加上 -type d 讓它只找目錄,不加的話,它會會連空檔案都找出來。

$ find /tmp -depth -empty -type d

配合 -exec 就可以將這些檔案全部刪掉啦。

$ find /tmp -depth -empty -type d -exec rmdir -v {} \;

這是一篇 Tips

大約從 J2SE 1.4/1.6 開始,Sun 所釋出的 Java runtime 開始支援 IPv6 連線功能。一般的 Linux 的套件系統 也開始支援 IPv6,許多系統預設是同時開啟 IPv4/IPv6 或稱為 Dual Stack 網路功能。

基本上,鼓勵各種軟體開始移植到 IPv6 網路上是一件好事。Java runtime 若在 dual-stack 的機器上,預設走 IPv6 位址,因為 IPv6 位址可同時走 IPv4/IPv6 網路。不過問題在於,若一般的 GNU/Linux Debian, Ubuntu 系統,預設會啟動 IPv6 介面,無論你所在網路是否有 IPv6 路由。

於是,你若在 Linux 上使用一些 Java 寫成的網路軟體,如 JDownloader 等,很有可能發生軟體運作後,卻什麽地方都連不上的症狀。解決辦法一是關閉 IPv6 網路功能,一則是利用 JRE 的參數,改為預設使用 IPv4 網路。

檢查 IPv6 是否驅動

首先,你若想確認是否開啟了 IPv6 網路,可於終端機下使用此指令判斷

$ ip addr|grep inet6

若出現了 inet6 之位址,即為開啟了 IPv6 網路。

你若想快速的關閉 IPv6 功能,可以利用 root 執行 ip 指令,直接刪除 inet6 位址

/sbin/ip addr del <ipv6address>/<prefixlength> dev ethX

舊版核心

在舊版核心,IPv6 功能是以模組方式存在,妳可以透過更改 modprobe (module-init-tools) 的設定,讓系統不載入對應驅動程式。關閉的方式很簡單,請修改 /etc/modprobe.d/ 之設定,如以 root 執行以下指令

# cat > /etc/modprobe.d/00local.conf <<EOF
alias net-pf-10 off
alias ipv6 off
EOF

更改之後,重新開機即可關閉 IPv6 功能。

新版核心

在新版的 Debian/Ubuntu 中使用 2.6 核心,因為內建 IPv6 驅動程式, 你得利用開機參數 (cmdline) 關閉之。作法是修改 /etc/default/grub 檔案,更改 GRUB_CMDLINE_LINUX_DEFAULT 一行,加入 ipv6.disable=1,如

GRUB_CMDLINE_LINUX_DEFAULT="ipv6.disable=1 quiet"

修改完畢後,請用 root 執行 update-grub 後,重新開機。

JRE 參數

另外一項作法是更改 JRE 參數,你若知道啟動該軟體的 shell script 位於何處,可新增一參數如下

$ java -Djava.net.preferIPv4Stack=true Main

這樣就可以要求 JVM 預設使用 IPv4 stack.

這是一篇 Tips.

修訂紀錄 (20100207): 補充利用 iproute 關閉 ipv6 方法,說明新舊版核心處理方式。

時常,你得將手上的軟體原始碼壓起來釋出給第三方使用、測試。特別是你希望提供 daily basics/ revision basics 讓使用者取得最新版軟體的時候。

由於最近都已經只用 git,依據我自己的習慣,希望能夠在檔名中使用簡碼版次,以便未來能夠追蹤出該版次的問題。稍微問了一下友人與查了一下文件,取得 abbreviated commit hash 的作法如下

git log --pretty=format:"%h" -1

若你想將整份程式碼壓縮起來,可以使用

git archive --format zip -o filename.zip HEAD

倘若想加上日期作為檔名,請使用

git archive --format zip -o $(git log --date=short --pretty=format:"%ad" -1).zip HEAD

若常常使用這個指令,有兩種作法,一是設定為 git alias. 另一則是利用 git 的 commands (verbs) 命名機制,在你的執行路徑 下,寫入一檔案名稱如 git-zip。並將上述指令加入檔案中,未來就可以使用 git zip 來產生最新版壓縮檔。

作法如
$ cat > ~/bin/git-zip
#!/bin/sh
git archive --format zip -o $(git log --pretty=format:"%h" -1).zip HEAD
$ chmod u+x ~/bin/git-zip
$ cd git-repository
$ git zip

另外,為了容易辨識版次,你也可以利用 gitattributes 在程式碼中加入 ident ($Id$) 作為標示。操作可參考 Lloyd Huang 所寫之 Howto.

這是一篇 Tip.

最近已經不太貢獻時間到 Debian 計畫中,雖然日常工作、辦事還是全部使用 Debian GNU/Linux。做的比較多的大概是幫忙踩地雷,跟偶爾回報一些自己常用軟體的小問題。

相較於商業軟體軟體,在自由軟體或開放原碼社群,最棒的使用經驗就是如果你碰到了甚麼問題,而且你描述得當的話,通常有機會得到開發者的注意與修正。但是你得「描述正確」。作為一個嘴砲開發者,我不甚喜歡收到毫無意義的回饋,過度熱情的回報人往往造成小開發團隊的極大困擾,數量跟質量往往成反比,而低質量的大量回報只會降低團隊士氣跟產能。如果可以的話,我希望可以收到許多高質量的回饋,也期許自己盡力這麼作。

這裡不談基本的回報問題的方式,你若用 Debian 請參考 How to report a bug in Debian using reportbugreportbug-ng,使用 Ubuntu 請參考 ReportingBugs。你若是新手,在你回報問題之前應該先讀 Simon Tatham如何有效地報告錯誤。這篇文章提供了一些基本的原則,你若碰到軟體使用的問題,應該試著按照文中的原則跟軟體開發者對話,可以避免殺死太多開發者的腦細胞,也可以幫你快點解決問題。

在先進的軟體中,不少已經內建 Crash reporter,像是 Gnome 的 Bug Buddy、Mozilla 的 Breakpad、Ubuntu 的 Apport 等等,這些工具會在你的軟體當掉時,自動收集一些系統資訊與程式狀態,並回報、收集到中央系統。這些資訊可以協助開發者收集一些技術性的資料,比「我的程式當掉了」這種回報更容易辨別錯誤所在。不過這些資訊只能提供一般性技術資料,並不方便作為直接除錯使用,大約可以利用於統計、分析軟體穩定性等加強軟體品質的用途。

若你恰巧不幸是軟體工程師,你可以試著利用 gdb 等試著收集更多資訊,甚至先進行初步的偵錯。但是我知道要求一般人重新編譯軟體加上除錯資訊等,再開啟暗黑 gdb 視窗下指令除錯,實在會嚇跑一些曾經習慣在其他平台只用 IDE 開發軟體的朋友。事實上,在 Debian 中還是有些工具可以讓你快速的進行軟體除錯,而且也有比較友善的工具可用。

你若要除錯,第一部大概是取得除錯資訊,預設的 Debian 套件是不含除錯資訊 (Debug symbols) 的,因為大部分的使用者不需要這些特別佔用空間的檔案。許多資深的 Debian Developer, 都會分別在包裝的套件時加上 Debug package,於是你可以在不重新編譯軟體的狀況下拿到同版的除錯訊息。 這些除錯套件的命名原則都是以 dbg 為結尾,例如以 Lifera 為例,你可以安裝 liferea-dbg

另外你也需要原本的程式碼,這點可以直接利用  apt-get source 指令取得,例如以下指令,系統會自動抓回你目前安裝版本的原始檔,並自動解開。
apt-get source liferea

而除錯時,你需要一個除錯工具,上述提到了 gdb 這個工具,對一些朋友說,熟悉指令的學習門檻似乎有點高,不過你若熟練 gdb 的使用技巧,可以直接利用其強大的 sciprt 功能進行許多自動化的測試或對程式直接插入命令。有機會還是應該學習一下。圖性化的使用介面亦有相當多選擇,像是 ddd 或是 KDbg 等。這裡推薦一下 Gnome 中新的工具 nemiver,若你曾經用過其他除錯工具,大概看到 nemiver 的介面就知道該何使用。它基本上就是原始碼閱讀工具加上 Call Stack, Variables, Breakpoints, Registers, Memory 等觀看與編輯工具,圖形介面非常簡單直覺。

這裡以 liferea 為例子,若你想對其除錯,可用以下指令,使 nemiver 載入 lifera 擺在 /usr/lib/debug 的除錯資訊。nemiver 會詢問你原始檔位置,你可以將其指到剛剛利用 apt-get 下載的原始碼目錄,這樣便可以一邊除錯一邊閱讀其程式碼或設定除錯點 (Break points)

LD_LIBRARY_PATH=/usr/lib/debug nemiver liferea

畫面會像是

nemiver

快快樂樂來抓蟲吧。

最近為了在網頁中使用一個 C Library,從頭寫了一個 PHP PECL Extension。期間自然做了一些調查與研究,在此寫下供其他朋友作為參考。

首先應瞭解開發 PECL 時,一些必要得知識,像是基本的 Zend SAPI、每個模組的生命週期、記憶體管理、ZVAL 參數的取得等等。關於這方面的知識,除了已經相對太舊的Zend API – Hacking the Core of PHP 外,Sara Golemon 算是著述的較多的開發者,他甚至出了一本書叫做《Extending and Embedding PHP》,去年在 ZendCon 2008 也談過一次 PHP Extension Writing

不過要完成一個 PECL Extension,大約不需要讀完一本書,Sara Golemon 在 2005 年時亦在 Zend Developer Zone 發表幾篇詳盡的技術文章,說明了最重要的幾個重點,讀過跟著做一次,大約就可以熟悉一些基本的技巧。我並沒有發現 Zend SAPI 的詳細文件,因此必須再翻翻 /usr/include/php5/Zend 下的 header files,看看其他 core extensions 的程式碼,大概就可以掌握完成一個 Extension 的知識。

Sara Golemon 的幾篇經典文章是

英文若嚥不下,或可參考 Huang Shiqiang簡體中文翻譯。Huang Shiqiang 尚做了一個以 C 為基礎的 PHP Framekwork – Kiss (計畫網頁),頗有趣。以效能為出發點的 framework 或 template engine 還有 Blitz 等。

讀過文章,瞭解基本的概念之後,就可以開始動手寫程式。首先,你得有開發環境,包含編譯檔案、目錄結構、文件封裝機制等。你自然可以動手複製一份別人的來改,或者你可以依照 PHP Manual 中的說明利用 ext_skel 來產出一個空白的專案。我自己是利用功能相較完整一點的 CodeGen_PECL。利用 Pear 裝好後,就可以利用 pecl-gen 生出一份空白的專案。

PHP Extension 預設利用 phpize 來自動生成 autotools scripts,對開發者來講,若要新增編譯參數或增加原始檔案,只需要增修 config.m4 中的內容即可,不用管整套的 autotools scripts,算是相當方便。config.m4 是用 m4 這個 macro processor 來處理,語法這裡就略過不提了,編譯文件應相當好找。

撰寫一個 Extenstion 的知識大概是這樣。補充說明,上述文件沒有提到的 PHP5 中的 Reflection API,你可以為每個函式加上 arginfo,可以方便一些工具自動取出這些 API 來用,作法請參考 Christian WeiskeHacking PHP5

另外一個值得一提的是做 Unit Testing 的方法,養成寫 test case 是維持軟體品質的好習慣。你若用了 phpize,系統應會自動生成 run-tests.php 等自動測試工具,你可以依照其設計寫一些自動測試的案例,每次編譯後可 make test 做自動測試,確保運作正常。在 IBM developerWorks 上有一篇淺析 PHP 官方自動化測試方法,值得一讀。

最後補充一點,這次我寫的延伸函式庫乃是 C 語言,若欲整合物件導向的  C++ 函式庫,可參考 Wrapping C++ Classes in a PHP Extension 一文。

這兩日試玩幾個 clutter 為基礎的軟體,像是 mutterGnome Shell 時,發現在我的 X200 上畫面的反應極慢,根本爆慢到了不堪用的地步。翻查了一陣子之後,知道大約是 Intel 顯示卡驅動程式 (GM45) 中的 sync-to-vblank 問題。

根據 Emmanuele Bassi說法,若安裝了新版的 Intel driver,必須開啟 KMS (kernel mode setting) 後,驅動程式才會有正確的 sync-to-vblank 行為。

這個問題大約從 Clutter 0.2 之後就開始了,影響到所有的 Clutter 為基礎的軟體,像是 Gnome 的接龍遊戲 (/usr/games/sol-clutter) 等等,若啟動接龍遊戲後畫面速度極慢,大約就是這個問題造成的。

正確的解決方法是啟用 KMS (作法: Debian, Ubuntu)。

若暫時不想啟用 KMS,你可以在環境參數中設定CLUTTER_VBLANK=none,如

# echo "CLUTTER_VBLANK=none" >> /etc/environment

然後重新啟動 X 即可。