SystemTap 是一個診斷 Linux 系統(tǒng)性能或功能問題的開源軟件,為了診斷系統(tǒng)問題或性能,開發(fā)者或調(diào)試人員只需要寫一些腳本,然后通過 SystemTap 提供的命令行接口就可以對正在運(yùn)行的內(nèi)核進(jìn)行診斷調(diào)試。
在 CentOS 上的安裝方法
首先需要安裝當(dāng)前內(nèi)核版本對應(yīng)的開發(fā)包和調(diào)試包(這一步非常重要并且最為繁瑣):
# #Installaion:
# rpm -ivh kernel-debuginfo-$(uname -r).rpm
# rpm -ivh kernel-debuginfo-common-$(uname -r).rpm
# rpm -ivh kernel-devel-$(uname -r).rpm
這些 rpm 包可以在該網(wǎng)址中下載: http://debuginfo.centos.org
安裝 systemtap:
# yum install systemtap
# ...
# 測試systemtap安裝成功否:
# stap -v -e 'probe vfs.read {printf("read performed\n"); exit()}'
Pass 1: parsed user script and 103 library script(s) using 201628virt/29508res/3144shr/26860data kb, in 10usr/190sys/219real ms.
Pass 2: analyzed script: 1 probe(s), 1 function(s), 3 embed(s), 0 global(s) using 296120virt/124876res/4120shr/121352data kb, in 660usr/1020sys/1889real ms.
Pass 3: translated to C into "/tmp/stapffFP7E/stap_82c0f95e47d351a956e1587c4dd4cee1_1459_src.c" using 296120virt/125204res/4448shr/121352data kb, in 10usr/50sys/56real ms.
Pass 4: compiled C into "stap_82c0f95e47d351a956e1587c4dd4cee1_1459.ko" in 620usr/620sys/1379real ms.
Pass 5: starting run.
read performed
Pass 5: run completed in 20usr/30sys/354real ms.
如果出現(xiàn)如上輸出表示安裝成功。
在 Ubuntu 上的安裝方法
對于 Ubuntu 上的安裝,參考 Ubuntu 官方維護(hù)的一個 wiki: https://wiki.ubuntu.com/Kernel/Systemtap
一般來說,僅需引入 ddeb 源,然后 apt-get
就能解決了。
由于 systemtap 需要依賴某些內(nèi)核特性,對于 Ubuntu Gutsy
(或更老的版本),必須重新編譯內(nèi)核。
編譯的步驟參見 systemtap 的這篇 wiki:
https://sourceware.org/systemtap/wiki/SystemtapOnUbuntu
另外,由于 Ubuntu 16.04 官方庫里的 systemtap 版本過舊(version 2.9),從 apt-get
安裝的 systemtap 有些情況下并不能正確地運(yùn)行。
這時候需要從 systemtap 源碼中編譯出可用的 systemtap。
編譯的過程參考 systemtap 的這篇文檔:
https://sourceware.org/git/?p=systemtap.git;a=blob_plain;f=README;hb=HEAD
大體上就這幾步:
# 下載依賴……
sudo apt install elfutils
sudo apt-get build-dep systemtap
# 下載最新的版本
wget/git ...
# 構(gòu)建,并祈禱能一次成功
./configure
make all
[sudo] make install
首先,需要下載 stapxx 工具包:Github地址。 該工具包中包含用 perl 寫的,會生成 stap 探測代碼并運(yùn)行的腳本。如果是要抓 Lua 級別的情況,請使用其中的 lj-lua-stacks.sxx。 由于 lj-lua-stacks.sxx 輸出的是文件絕對路徑和行號,要想匹配具體的 Lua 代碼,需要用 fix-lua-bt 進(jìn)行轉(zhuǎn)換。
# ps -ef | grep nginx (ps:得到類似這樣的輸出,其中15010即使worker進(jìn)程的pid,后面需要用到)
hippo 14857 1 0 Jul01 ? 00:00:00 nginx: master process /opt/openresty/nginx/sbin/nginx -p /home/hippo/skylar_server_code/nginx/main_server/ -c conf/nginx.conf
hippo 15010 14857 0 Jul01 ? 00:00:12 nginx: worker process
# ./samples/lj-lua-stacks.sxx --arg time=5 --skip-badvars -x 15010 > tmp.bt (-x 是要抓的進(jìn)程的 pid, 探測結(jié)果輸出到 tmp.bt)
# ./fix-lua-bt tmp.bt > flame.bt (處理 lj-lua-stacks.sxx 的輸出,使其可讀性更佳)
其次,下載 Flame-Graphic 生成包:Github地址,該工具包中包含多個火焰圖生成工具,其中,stackcollapse-stap.pl 才是為 SystemTap 抓取的棧信息的生成工具
# stackcollapse-stap.pl flame.bt > flame.cbt
# flamegraph.pl flame.cbt > flame.svg
如果一切正常,那么會生成 flame.svg,這便是火焰圖,用瀏覽器打開即可。
ps:如果在執(zhí)行 lj-lua-stacks.sxx 的時間周期內(nèi)(上面的命令是 5 秒), 抓取的 worker 沒有任何業(yè)務(wù)在跑,那么生成的火焰圖便沒有業(yè)務(wù)內(nèi)容。為了讓生成的火焰圖更有代表性,我們通常都會在抓取的同時進(jìn)行壓測。