1. 程式人生 > >Linux除錯分析診斷利器——strace

Linux除錯分析診斷利器——strace

Linux除錯分析診斷利器——strace

 

     strace是個功能強大的Linux除錯分析診斷工具,可用於跟蹤程式執行時程序系統呼叫(system call)和所接收的訊號,尤其是針對原始碼不可讀或原始碼無法再編譯的程式。

     在Linux系統中,使用者程式執行在一個沙箱(sandbox)裡,使用者程序不能直接訪問計算機硬體裝置。當程序需要訪問硬體裝置(如讀取磁碟檔案或接收網路資料等)時,必須由使用者態模式切換至核心態模式,通過系統呼叫訪問硬體裝置。strace可跟蹤程序產生的系統呼叫,包括引數、返回值和執行所消耗的時間。若strace沒有任何輸出,並不代表此時程序發生阻塞;也可能程式程序正在自己的沙箱裡執行某些不需要與系統其它部分發生通訊的事情。strace從核心接收資訊,且無需以任何特殊方式來構建核心。

     strace命令格式如下:

strace [-dffhiqrtttTvVxx] [-a column] [-e expr] [-o file] [-p pid] [-s strsize] [-u username] [-E var=val] [command [arg ...]] 或

strace -c [-e expr] [-O overhead] [-S sortby] [-E var=val] [command [arg ...]]

     通過不同的選項開關,strace提供非常豐富的跟蹤功能。最簡單的應用是,跟蹤可執行程式執行時的整個生命週期,將所呼叫的系統呼叫的名稱、引數和返回值輸出到標準錯誤輸出stderr(即螢幕)或-o選項所指定的檔案。注意,命令(command)必須位於選項列表之後。

     詳細的strace命令選項列舉如下:

選項

含義

-c

統計和報告每個系統呼叫所執行的時間、呼叫次數和出錯次數等

-d

輸出strace關於標準錯誤的除錯資訊

-f

跟蹤當前程序及其通過fork系統呼叫所建立的子程序

-ff

常與-o選項聯合使用,不同程序(子程序)的跟蹤結果分別輸出到相應的filename. pid檔案中,pid是各個程序號

-F

嘗試跟蹤vfork系統呼叫。否則即使開啟-f選項,vfork也不會被跟蹤

-h

顯示幫助資訊

-i

顯示發生系統呼叫時的指令指標(IP)暫存器值

-q

抑制(禁止輸出)關於結合(attaching)、脫離(detaching)的訊息。當輸出重定向到一個檔案時,自動抑制此類訊息

-r

顯示每個系統呼叫發生時的相對時間戳,即連續的系統呼叫起點之間的時間差

-t

-tt

-ttt

-t在每行輸出前新增絕對時間戳(當前時鐘)資訊,精確到秒級

-tt在每行輸出前新增絕對時間戳資訊,精確到微秒級

-ttt在每行輸出前新增相對時間資訊,格式為”自紀元時間起經歷的秒數.微秒數”

-T

顯示每個系統呼叫所耗費的時間,其時間開銷在輸出行最右側的尖括號內

-V

顯示strace的版本資訊

-v

冗餘顯示模式:顯示系統呼叫中argv[]、envp[]、stat、termio(s)等陣列/結構體引數所有的元素/成員內容。這些陣列/結構體因使用頻繁,預設僅顯示其元素/成員的合理子集

-x

以16進位制形式顯示非標準(non-ascii)字串,如"/x08"。預設為8進位制,如"/10"

-xx

以16進位制形式顯示所有字串

-a column

設定顯示系統呼叫返回值的列位置,預設為40(從0開始),即"="出現在第40列

-e expr

指定一個表示式,用於限定跟蹤哪些事件及如何跟蹤。其格式為[qualifier=][!]all或[qualifier=][!]value1[,value2]...。

qualifier取值為trace(預設)、abbrev、verbose、raw、signal、read或write。value是用於限定的符號(包括all和none)或數字。感嘆號為否定符號,如-eopen等價於-e trace=open,表示只跟蹤open系統呼叫;而-e trace=!open表示跟蹤除open外的其他系統呼叫。

注意某些shell用!表示執行歷史記錄裡的命令,此時可能借助引號、轉義符號(/)。

-e trace=set:跟蹤指定的系統呼叫列表,如-e trace=open,close,read,write表示只跟蹤這四種系統呼叫。預設為set=all。

-e trace=file:跟蹤以指定檔名做引數的所有系統呼叫。

-e trace=process:跟蹤涉及程序管理的所有系統呼叫,可用於觀察程序的fork、wait和exec階段。

-e trace=network:跟蹤網路相關的所有系統呼叫。

-e strace=signal:跟蹤所有與系統訊號相關的系統呼叫。

-e trace=ipc:跟蹤所有與程序間通訊有關的系統呼叫。

-e abbrev=set:指定哪些系統呼叫中的大型陣列或結構體內容縮減顯示,如strace -e abbrev=execve ./test僅顯示execve呼叫中argv[]和envp[]的部分內容。預設為abbrev=all, abbrev=none等價於-v選項。

-e verbose=set:指定哪些系統呼叫中的大型陣列或結構體內容完整顯示,集合外的呼叫其陣列或結構體顯示為地址。預設為verbose=all。

-e raw=set:指定哪些系統呼叫中的引數以原始未解碼的形式(即16進位制)顯示。當用戶不信任strace解碼或需要了解引數實際數值時有用。

-e signal=set:跟蹤指定的訊號列表,預設為signal=all。如signal=!SIGIO(或signal=!io)表示不跟蹤SIGIO訊號。

-e read=set:以16進位制和ASCII碼對照形式顯示從指定檔案描述符中讀出的所有資料,如-e read=3,5可觀察檔案描述符3和5上的輸入動作。該選項獨立於系統呼叫read的常規跟蹤(由-e trace=read選項控制)。

-e write=set:以16進位制和ASCII碼對照形式顯示寫入指定檔案描述符的所有資料。

-o file

strace輸出資訊預設顯示到標準錯誤輸出,該選項將輸出資訊寫入檔案file中。以下兩條命令等效:

strace -c -o test.txt ./test

strace -c ./test 2>test.txt

-O overhead

Set the overhead for tracing system calls to overhead microseconds. This is useful for overriding the default heuristic for guessing how much time is spent in mere measuring when timing system calls using the -c option. The acuracy of the heuristic can be gauged by timing a given program run without tracing (使用time命令) and comparing the accumulated system call time to the total produced using -c.

-p pid

指定待跟蹤的程序號(pid),可用Ctrl-C終止跟蹤而被跟蹤程序繼續執行。可指定多達32個(-p pid)選項以同時跟蹤多個程序。該選項常用於除錯後臺程序

-s strsize

限制每行輸出中字串(如read引數)的最大顯示長度,預設32位元組。但檔名總是完整顯示

-S sortby

按指定規則對-c選項的輸出直方圖進行排序。sortby取值可為time、calls、name和nothing(預設time)

-u username

用指定使用者的UID和/或GID身份執行待跟蹤程式

-E var=val

將var=val放入命令的環境變數列表

-E var

從命令的環境變數列表中移除var

     例如,命令strace -o out.txt -T -tt -e trace=all -p 2899表示跟蹤2899程序的所有系統呼叫,並統計系統呼叫的時間開銷,以及呼叫起始時間(以視覺化的時分秒格式顯示),最後將記錄結果存入out.txt檔案。

     為便於說明,使用strace跟蹤ls -l命令執行過程(strace ls -l),前幾行輸出如下:

     strace記錄程式所產生的每次系統呼叫,並以類似C的格式(無論建立該程式時使用何種程式語言)各自顯示為單獨的一行。每行起始為系統呼叫的函式名,括號內為引數,該呼叫的返回值則顯示在等號右側。當引數為陣列或結構體時,顯示其元素(方括號)或成員(花括號)內容,見execve和fstat64。當引數為bit時,使用方括號並用空格隔開每項引數,如sigprocmask(SIG_BLOCK,[CHLD TTOU],[]) = 0,第二個引數代表訊號SIGCHLD和SIGTTOU;若bit型引數全部置位,則輸出如sigprocmask(SIG_UNBLOCK,~[],NULL) = 0,此處第二個引數全部置位。

     通過使用-c選項,strace可統計分析程序所有的系統呼叫(strace -c ./ChangeSysTime),如:

     可看到程式呼叫哪些系統函式,呼叫次數、所耗時間及出錯次數等資訊,有助於分析程式執行速度瓶頸。同時注意到,settimeofday調用出錯兩次,而該函式在ChangeSysTime程式中被顯式呼叫兩次,亦即這兩次呼叫均出錯!但ChangeSysTime程式中並未對settimeofday呼叫作出錯處理,故在執行中沒有輸出任何錯誤提示。假定程式原始碼不可修改,則此時就可藉助strace找出錯誤所在(strace -e trace=settimeofday ./ChangeSysTime): 

     真相大白,原來呼叫settimeofday函式時因操作許可權不夠而被拒絕(需要root許可權)!注意,第2、3和5行輸出為ChangeSysTime程式列印輸出。

轉自:https://www.cnblogs.com/clover-toeic/p/3738156.html