為什麼要用 Unix 命令列工具#
除錯時經常會遇到前所未見的問題,你慣用的 IDE 可能缺乏足夠的工具來深入探索。Unix 命令列工具是通用型工具,可以透過 pipeline 組合成強大的分析流程,輕鬆處理各種文字資料。
這些文字資料包括:
- 程式原始碼、程式日誌
- 版本控制歷史、檔案清單
- Symbol tables、錯誤訊息
- 測試結果、profiling 數據
比起用 Perl、Python 等腳本語言寫一個獨立程式,直接在 shell 中組合 Unix 工具往往更快、更靈活。你可以逐步建構命令,直到得到想要的結果。
除錯 pipeline 的基本模式#
大多數除錯用的 one-liner 遵循這個模式:取得 (fetch) → 選取 (select) → 處理 (process) → 彙整 (summarize),並用 pipeline (|) 串接各步驟。
取得資料#
- 文字檔案:直接作為標準輸入
- object 檔案:使用
nm(Unix)、dumpbin(Windows)、javap(Java) - 壓縮檔:使用
tar、jar、ar - 檔案系統:使用
find搜尋 - 網路資料:使用
curl或wget - 編譯器錯誤:用
2>&1或2>filename重導 standard error
# 找出所有 object 檔案中呼叫 exit 的模組
nm -A *.o | grep 'U exit$'選取與過濾#
cut:從固定欄位或分隔符號中擷取特定欄位sed:用正規表達式替換來擷取特定部分grep:篩選符合條件的列;-v過濾不要的列fgrep:用-f旗標比對固定字串清單
# 從 system trace 輸出中取得成功開啟的檔案名稱
grep '^open(' trace.out |
grep -v '= -1' |
awk -F\" '{print $2}'處理與彙整#
sort:排序(支援多種排序鍵與數值排序)uniq -c:計算重複次數wc -l:計算行數head/tail:取最前或最後 N 筆diff:比較兩次執行的結果comm:比較兩個已排序的清單awk:進階欄位處理與數值運算
# 找出某檔案最常修改的作者
git blame --line-porcelain Foo.java |
grep '^author ' |
sort |
uniq -c |
sort -rn |
head用 Shell 膠水連接一切#
xargs:將清單傳遞為多個命令引數-print0/-0:處理含空白的檔案名稱while read:迴圈處理每一行
# 找出修改 foo.cpp 後,含最多 "access failure" 的 log 檔
find /var/log/acme -type f -cnewer ~/src/acme/foo.cpp -print0 |
xargs -0 fgrep -c 'access failure' |
sort -t: -rn -k2 |
head -1當中間處理步驟變得太複雜時,不要害怕使用暫存檔案來分段處理。
重點回顧#
- 透過 Unix 命令組合 pipeline,可以快速完成複雜的文字資料分析
- 基本模式為「取得 → 選取 → 處理 → 彙整」
grep、sort、uniq、awk、xargs是除錯時最常用的工具- 善用
2>&1重導 standard error 以便分析編譯器或程式的錯誤輸出