在這貨上花費了不少時間,都是受了@agentzh 大神的蠱惑:) 他寫的nginx-systemtap-toolkit監測的數據很有價值,對於系統優化實在是利器。
最早折騰systemtap,是在Ubuntu 12.04上搞的,內核版本是3.8.0-29-generic,流程參考官方教程。因為12.04版本比較新,所以不需要重新編譯內核了。然后添加帶調試信息的內核,以及相關的Linux頭文件。整個過程還算順利,就是公司網速比較慢。下載完成后,用ubuntu官方倉庫自帶的systemtap 1.6,卻出現各種奇怪的C編譯錯誤,於是換到了git clone下來的最新版本。這次錯誤信息友好了很多,但tapset的腳本跟內核的dwarf信息似乎對應不上,報semantic error: not accessible at this address [man error::dwarf]。至此,ubuntu上的systemtap只能打出hello world,其他腳本都跑不了,遂放棄。教訓是,systemtap要新版,內核要老版,若用老systemtap和新內核,一般是會掛的。
對systemtap的用戶態監控還是很口水,雖然我司用的是自己寫的定制語言,但是-g編譯后應該可以監控私有語言的腳本棧,進而分析性能瓶頸。於是,死皮賴臉搶奪了一台CentOS的機器做測試。機器版本如下:
[root@localhost systemtap]# uname -rm 2.6.32-279.el6.x86_64 x86_64 [root@localhost systemtap]# cat /etc/redhat-release CentOS release 6.3 (Final)
用的systemtap版本是最新的。跟Ubuntu相比,CentOS的包管理就比較差了,內核的調試信息包需要自己手動下載安裝。參考官方教程,安裝debuginfo-common和debuginfo后,就可以開搞了。還好,這次不需要編譯內核。安裝好systemtap后,跑起來卻出現這個問題:
stap -e 'probe begin { log("hello world") exit() }'
提示:
Checking "/lib/modules/2.6.32-279.el6.x86_64/build/.config" failed with error: 沒有那個文件或目錄
檢查了一下相關的目錄,/lib/modules/2.6.32-279.el6.x86_64/是一個軟連接,鏈接到/usr/src/kernels/里去的。而2.6.32-358.23.2.el6.x86_64這個目錄是真的沒有,有的是2.6.32-358.23.2.el6.x86_64。谷歌了一下,這個目錄是kernel-devel包的,通過yum安裝的是最新的2.6.32-358.23.2.el6.x86_64,跟當前運行的內核不符。繼續放狗,找到2.6.32-279.el6.x86_64的kernel-devel rpm包,安裝完就有對應目錄了。試了一下iotop終於成功了。
看了一下,systemtap似乎是根據寫的probe編譯成二進制模塊,加載到內核里執行的。所以systemtap會在home目錄下建立一個cache目錄,避免重復編譯相同的腳本。而nginx-systemtap-toolkit對Lua的棧探測,是通過監視LuaL開頭的函數實現的,接下來准備按他的思路搞一下我們的私有語言。