天天看點

Linux strace指令簡介輸出參數含義strace參數指令執行個體strace案例

strace常用來跟蹤程序執行時的系統調用和所接收的信号。 在Linux世界,程序不能直接通路硬體裝置,當程序需要通路硬體裝置(比如讀取磁盤檔案,接收網絡資料等等)時,必須由使用者态模式切換至核心态模式,通 過系統調用通路硬體裝置。strace可以跟蹤到一個程序産生的系統調用,包括參數,傳回值,執行消耗的時間。

每一行都是一條系統調用,等号左邊是系統調用的函數名及其參數,右邊是該調用的傳回值。

strace 顯示這些調用的參數并傳回符号形式的值。strace 從核心接收資訊,而且不需要以任何特殊的方式來建構核心。

 -c 統計每一系統調用的所執行的時間,次數和出錯的次數等. 

通用的完整用法:

上面的含義是 跟蹤28979程序的所有系統調用(-e trace=all),并統計系統調用的花費時間,以及開始時間(并以可視化的時分秒格式顯示),最後将記錄結果存在output.txt檔案裡面。

在理想世界裡,每當一個程式不能正常執行一個功能時,它就會給出一個有用的錯誤提示,告訴你在足夠的改正錯誤的線索。但遺憾的是,我們不是生活在理想世界 裡,起碼不總是生活在理想世界裡。有時候一個程式出現了問題,你無法找到原因。

這就是調試程式出現的原因。strace是一個必不可少的 調試工具,strace用來監視系統調用。你不僅可以調試一個新開始的程式,也可以調試一個已經在運作的程式(把strace綁定到一個已有的PID上 面)。

首先讓我們看一個真實的例子:啟動KDE時出現問題

前一段時間,我在 啟動KDE的時候出了問題,KDE的錯誤資訊無法給我任何有幫助的線索。

對 我來說這個錯誤資訊沒有太多意義,隻是一個對KDE來說至關重要的負責程序間通信的程式無法啟動。我還可以知道這個錯誤和ICE協定(Inter Client Exchange)有關,除此之外,我不知道什麼是KDE啟動出錯的原因。

我決定采用strace看一下在啟動 dcopserver時到底程式做了什麼:

這裡 -f -F選項告訴strace同時跟蹤fork和vfork出來的程序,-o選項把所有strace輸出寫到~/dcop-strace.txt裡 面,dcopserver是要啟動和調試的程式。

再次出現錯誤之後,我檢查了錯誤輸出檔案dcop-strace.txt,檔案裡有很多 系統調用的記錄。在程式運作出錯前的有關記錄如下:

<a target="_blank"></a>

其中第一行顯示程式試圖建立/tmp/.ICE-unix目錄,權限為0777,這個操作因為目錄已經存在而失敗了。第二個系統調用(lstat64)檢查 了目錄狀态,并顯示這個目錄的權限是0755,這裡出現了第一個程式運作錯誤的線索:程式試圖建立屬性為0777的目錄,但是已經存在了一個屬性為 0755的目錄。第三個系統調用(unlink)試圖删除一個檔案,但是這個檔案并不存在。這并不奇怪,因為這個操作隻是試圖删掉可能存在的老檔案。

但是,第四行确認了錯誤所在。他試圖綁定到/tmp/.ICE-unix/dcop27207-1066844596,但是出現了拒絕通路錯誤。. ICE_unix目錄的使用者群組都是root,并且隻有所有者具有寫權限。一個非root使用者無法在這個目錄下面建立檔案,如果把目錄屬性改成0777, 則前面的操作有可能可以執行,而這正是第一步錯誤出現時進行過的操作。

是以我運作了chmod 0777 /tmp/.ICE-unix之後KDE就可以正常啟動了,問題解決了,用strace進行跟蹤調試隻需要花很短的幾分鐘時間跟蹤程式運作,然後檢查并分 析輸出檔案。

說明:運作chmod 0777隻是一個測試,一般不要把一個目錄設定成所有使用者可讀寫,同時不設定粘滞位(sticky bit)。給目錄設定粘滞位可以阻止一個使用者随意删除可寫目錄下面其他人的檔案。一般你會發現/tmp目錄因為這個原因設定了粘滞位。KDE可以正常啟動 之後,運作chmod +t /tmp/.ICE-unix給.ICE_unix設定粘滞位。

starce 的另一個用處是解決和動态庫相關的問題。當對一個可執行檔案運作ldd時,它會告訴你程式使用的動态庫和找到動态庫的位置。但是如果你正在使用一個比較老 的glibc版本(2.2或更早),你可能會有一個有bug的ldd程式,它可能會報告在一個目錄下發現一個動态庫,但是真正運作程式時動态連接配接程式 (/lib/ld-linux.so.2)卻可能到另外一個目錄去找動态連接配接庫。這通常因為/etc/ld.so.conf和 /etc/ld.so.cache檔案不一緻,或者/etc/ld.so.cache被破壞。在glibc 2.3.2版本上這個錯誤不會出現,可能ld-linux的這個bug已經被解決了。

盡管這樣,ldd并不能把所有程式依賴的動态庫列出 來,系統調用dlopen可以在需要的時候自動調入需要的動态庫,而這些庫可能不會被ldd列出來。作為glibc的一部分的NSS(Name Server Switch)庫就是一個典型的例子,NSS的一個作用就是告訴應用程式到哪裡去尋找系統帳号資料庫。應用程式不會直接連接配接到NSS庫,glibc則會通 過dlopen自動調入NSS庫。如果這樣的庫偶然丢失,你不會被告知存在庫依賴問題,但這樣的程式就無法通過使用者名解析得到使用者ID了。讓我們看一個例子:

whoami程式會給出你自己的使用者名,這個程式在一些需要知道運作程式的真正使用者的腳本程式裡面非常有用,whoami的一個示例 輸出如下:

假設因為某種原因在升 級glibc的過程中負責使用者名和使用者ID轉換的庫NSS丢失,我們可以通過把nss庫改名來模拟這個環境:

這裡你可以看到,運作whoami時出現了錯誤,ldd程式的輸出不會提供有用的幫助:

你隻會看到whoami依賴Libc.so.6和ld-linux.so.2,它沒有給出運作whoami所必須的其他庫。這裡時用strace跟蹤 whoami時的輸出:

你可以發現在不同目錄下面查找libnss.so.2的嘗試,但是都失敗了。如果沒有strace這樣的工具,很難發現這個錯誤是由于缺少動态庫造成的。現 在隻需要找到libnss.so.2并把它放回到正确的位置就可以了。 

如果你已經知道你要找什麼,你可以讓strace隻跟蹤一些類型的系統調用。例如,你需要看看在configure腳本裡面執行的程式,你需要監視的系統調 用就是execve。讓strace隻記錄execve的調用用這個指令:

下一篇: AMQP協定

繼續閱讀