導航:首頁 > 程序命令 > linuxstrace命令

linuxstrace命令

發布時間:2025-03-09 06:16:46

linux入門之strace指令詳解

Linux操作系統以其穩定性和強大的功能而廣受歡迎。在Linux系統中,有許多強大的命令行工具,其中之一便是strace。strace是一個診斷和調試工具,它能夠跟蹤系統調用和信號。系統調用是程序與操作系統內核交互的介面。當程序需要操作系統提供的服務時,如文件操作、網路通信、進程管理等,就會通過系統調用請求這些服務。系統調用是操作系統功能的基礎,是程序運行時與硬體隔離的橋梁。strace的主要作用是監控和分析程序執行過程中的系統調用和接收到的信號。通過strace,用戶可以了解程序在運行時請求了哪些系統調用,這些調用的參數是什麼,以及操作系統對這些調用的響應。這對於調試程序、分析程序行為、優化性能等方面都非常有用。strace的基本用法很簡單。其基本格式如下:其中,[options]是strace的選項,program是需要跟蹤的程序,[program arguments]是傳遞給程序的參數。例如,要跟蹤ls命令的執行過程,可以使用以下命令:這將輸出ls命令執行過程中的所有系統調用和信號。strace有許多選項,以下是一些常用的選項:實例:跟蹤特定系統調用如果要跟蹤程序在執行過程中對read系統調用的使用,可以使用以下命令:這將只顯示ls命令執行過程中的read系統調用。實例:統計系統調用使用-c選項可以統計程序執行過程中各個系統調用的使用次數:執行後,strace會輸出一個統計表,顯示了每個系統調用被調用的次數。實例:跟蹤子進程使用-f選項可以讓strace跟蹤由程序創建的所有子進程:這將輸出ls命令及其所有子進程的系統調用跟蹤信息。實例:輸出時間戳使用-t選項可以在輸出中包含每個系統調用的時間戳:這將顯示每次系統調用發生的時間,有助於分析程序的執行時間。strace的輸出有時可能非常龐大,特別是當程序進行大量系統調用時。為了更方便地分析輸出,可以使用grep等工具對strace的輸出進行過濾。例如:這將只顯示與open系統調用相關的統計信息。strace還可以用於性能分析。通過跟蹤系統調用,可以發現程序中的瓶頸。例如,如果一個程序頻繁地進行文件讀寫操作,可能會導致性能問題。通過分析strace的輸出,可以找到這些瓶頸並進行優化。strace是一個功能強大的工具,對於Linux初學者來說,掌握它能夠幫助更好地理解程序與操作系統的交互。通過本文的介紹,初學者應該能夠開始使用strace來跟蹤系統調用和信號,以及進行基本的程序分析。隨著實踐的深入,strace將成為解決Linux系統下問題的強大助手。

② linux系統strace命令用法

linux的strace命令用法

調用:

strace [ -dffhiqrtttTvxx ] [ -acolumn ] [ -eexpr ] ...

[ -ofile ] [ -ppid ] ... [ -sstrsize ] [ -uusername ] [ command [ arg ... ] ]

strace -c [ -eexpr ] ... [ -Ooverhead ] [ -Ssortby ] [ command [ arg ... ] ]

功能:

跟蹤程式執行時的系統調用和所接收的信號.通常的用法是strace執行一直到commande結束.

並且將所調用的系統調用的名稱、參數和返回值輸出到標准輸出或者輸出到-o指定的文件.

strace是一個功能強大的調試,分析診斷工具.你將發現他是一個極好的幫手在你要調試一個無法看到源碼或者源碼無法在編譯的程序.

你將輕松的學習到一個軟體是如何通過系統調用來實現他的功能的.而且作為一個程序設計師,你可以了解到在用戶態和內核態是如何通過系統調用和信號來實現程序的功能的.

strace的每一行輸出包括系統調用名稱,然後是參數和返回值.這個例子:

strace cat /dev/null

他的輸出會有:

open(\"/dev/null\",O_RDONLY) = 3

有錯誤產生時,一般會返回-1.所以會有錯誤標志和描述:

open(\"/foor/bar\",)_RDONLY) = -1 ENOENT (no such file or directory)

信號將輸出喂信號標志和信號的描述.跟蹤並中斷這個命令\"sleep 600\":

sigsuspend({}

--- SIGINT (Interrupt) ---

+++ killed by SIGINT +++

參數的輸出有些不一致.如shell命令中的 \">>tmp\",將輸出:

open(\"tmp\",O_WRONLY|O_APPEND|A_CREAT,0666) = 3

對於結構指針,將進行適當的顯示.如:\"ls -l /dev/null\":

lstat(\"/dev/null\",{st_mode=S_IFCHR|0666},st_rdev=makdev[1,3],...}) = 0

請注意\"struct stat\" 的聲明和這里的輸出.lstat的第一個參數是輸入參數,而第二個參數是向外傳值.

當你嘗試\"ls -l\" 一個不存在的文件時,會有:

lstat(/foot/ball\",0xb004) = -1 ENOENT (no such file or directory)

char*將作為C的字元串類型輸出.沒有字元串輸出時一般是char* 是一個轉義字元,只輸出字元串的長度.

當字元串過長是會使用\"...\"省略.如在\"ls -l\"會有一個gepwuid調用讀取password文件:

read(3,\"root::0:0:System Administrator:/\"...,1024) = 422

當參數是結構數組時,將按照簡單的指針和數組輸出如:

getgroups(4,[0,2,4,5]) = 4

關於bit作為參數的情形,也是使用方括弧,並且用空格將每一項參數隔開.如:

sigprocmask(SIG_BLOCK,[CHLD TTOU],[]) = 0

這里第二個參數代表兩個信號SIGCHLD 和 SIGTTOU.如果bit型參數全部置位,則有如下的輸出:

sigprocmask(SIG_UNBLOCK,~[],NULL) = 0

這里第二個參數全部置位.

參數說明:

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

-d 輸出strace關於標准錯誤的調試信息.

-f 跟蹤由fork調用所產生的子進程.

-ff 如果提供-o filename,則所有進程的跟蹤結果輸出到相應的filename.pid中,pid是各進程的進程號.

-F 嘗試跟蹤vfork調用.在-f時,vfork不被跟蹤.

-h 輸出簡要的幫助信息.

-i 輸出系統調用的入口指針.

-q 禁止輸出關於脫離的消息.

-r 列印出相對時間關於,,每一個系統調用.

-t 在輸出中的每一行前加上時間信息.

-tt 在輸出中的每一行前加上時間信息,微秒級.

-ttt 微秒級輸出,以秒了表示時間.

-T 顯示每一調用所耗的時間.

-v 輸出所有的系統調用.一些調用關於環境變數,狀態,輸入輸出等調用由於使用頻繁,默認不輸出.

-V 輸出strace的版本信息.

-x 以十六進制形式輸出非標准字元串

-xx 所有字元串以十六進制形式輸出.

-a column

設置返回值的輸出位置.默認為40.

-e expr

指定一個表達式,用來控制如何跟蹤.格式如下:

[qualifier=][!]value1[,value2]...

qualifier只能是 trace,abbrev,verbose,raw,signal,read,write其中之一.value是用來限定的符號或數字.默認的qualifier是 trace.感嘆號是否定符號.例如:

-eopen等價於 -e trace=open,表示只跟蹤open調用.而-etrace!=open表示跟蹤除了open以外的其他調用.有兩個特殊的符號 all 和 none.

注意有些shell使用!來執行歷史記錄里的命令,所以要使用\\.

-e trace=set

只跟蹤指定的系統調用.例如:-e trace=open,close,rean,write表示只跟蹤這四個系統調用.默認的為set=all.

-e trace=file

只跟蹤有關文件操作的系統調用.

-e trace=process

只跟蹤有關進程式控制制的系統調用.

-e trace=network

跟蹤與網路有關的所有系統調用.

-e strace=signal

跟蹤所有與系統信號有關的系統調用

-e trace=ipc

跟蹤所有與進程通訊有關的系統調用

-e abbrev=set

設定strace輸出的系統調用的結果集.-v 等與 abbrev=none.默認為abbrev=all.

-e raw=set

將指定的系統調用的參數以十六進制顯示.

-e signal=set

指定跟蹤的系統信號.默認為all.如signal=!SIGIO(或者signal=!io),表示不跟蹤SIGIO信號.

-e read=set

輸出從指定文件中讀出的數據.例如:

-e read=3,5

-e write=set

輸出寫入到指定文件中的數據.

-o filename

將strace的輸出寫入文件filename

-p pid

跟蹤指定的進程pid.

-s strsize

指定輸出的字元串的最大長度.默認為32.文件名一直全部輸出.

-u username

以username的UID和GID執行被跟蹤的命令.

用strace調試程序

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

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

首先讓我們看一個真實的例子:

[BOLD]啟動KDE時出現問題[/BOLD]

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

代碼:

_KDE_IceTransSocketCreateListener: failed to bind listener

_KDE_: ...SocketCreateListener() failed

_KDE_: failed to create listener for local

Cannot establish any listening sockets DCOPServer self-test failed.

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

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

代碼:

strace -f -F -o ~/dcop-strace.txt dcopserver

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

再次出現錯誤之後,我檢查了錯誤輸出文件dcop-strace.txt,文件里有很多系統調用的記錄。在程序運行出錯前的有關記錄如下:

代碼:

27207 mkdir("/tmp/.ICE-unix", 0777) = -1 EEXIST (File exists)

27207 lstat64("/tmp/.ICE-unix", {st_mode=S_IFDIR|S_ISVTX|0755, st_size=4096, ...}) = 0

27207 unlink("/tmp/.ICE-unix/dcop27207-1066844596") = -1 ENOENT (No such file or directory)

27207 bind(3, {sin_family=AF_UNIX, path="/tmp/.ICE-unix/dcop27207-1066844596"}, 3 = -1 EACCES (Permission denied)

27207 write(2, "_KDE_IceTrans", 13) = 13

27207 write(2, "SocketCreateListener: failed to "..., 46) = 46

27207 close(3) = 0 27207 write(2, "_KDE_IceTrans", 13) = 13

27207 write(2, "SocketUNIXCreateListener: ...Soc"..., 59) = 59

27207 umask(0) = 0 27207 write(2, "_KDE_IceTrans", 13) = 13

27207 write(2, "MakeAllCOTSServerListeners: fail"..., 64) = 64

27207 write(2, "Cannot establish any listening s"..., 39) = 39

其中第一行顯示程序試圖創建/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設置粘滯位。

[BOLD]解決庫依賴問題[/BOLD]

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的一個示例輸出如下:

代碼:

# whoami

root

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

代碼:

# mv /lib/libnss_files.so.2 /lib/libnss_files.so.2.backup

# whoami

whoami: cannot find username for UID 0

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

代碼:

# ldd /usr/bin/whoami

libc.so.6 => /lib/libc.so.6 (0x4001f000)

/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)

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

代碼:

strace -o whoami-strace.txt whoami

open("/lib/libnss_files.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)

open("/lib/i686/mmx/libnss_files.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)

stat64("/lib/i686/mmx", 0xbffff190) = -1 ENOENT (No such file or directory)

open("/lib/i686/libnss_files.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)

stat64("/lib/i686", 0xbffff190) = -1 ENOENT (No such file or directory)

open("/lib/mmx/libnss_files.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)

stat64("/lib/mmx", 0xbffff190) = -1 ENOENT (No such file or directory)

open("/lib/libnss_files.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)

stat64("/lib", {st_mode=S_IFDIR|0755, st_size=2352, ...}) = 0

open("/usr/lib/i686/mmx/libnss_files.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)

stat64("/usr/lib/i686/mmx", 0xbffff190) = -1 ENOENT (No such file or directory)

open("/usr/lib/i686/libnss_files.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)

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

[BOLD]限制strace只跟蹤特定的系統調用[/BOLD]

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

代碼:

strace -f -o configure-strace.txt -e execve ./configure

部分輸出結果為:

代碼:

2720 execve("/usr/bin/expr", ["expr", "a", ":", "(a)"], [/* 31 vars */]) = 0

2725 execve("/bin/basename", ["basename", "./configure"], [/* 31 vars */]) = 0

2726 execve("/bin/chmod", ["chmod", "+x", "conftest.sh"], [/* 31 vars */]) = 0

2729 execve("/bin/rm", ["rm", "-f", "conftest.sh"], [/* 31 vars */]) = 0

2731 execve("/usr/bin/expr", ["expr", "99", "+", "1"], [/* 31 vars */]) = 0

2736 execve("/bin/ln", ["ln", "-s", "conf2693.file", "conf2693"], [/* 31 vars */]) = 0

你已經看到了,strace不僅可以被程序員使用,普通系統管理員和用戶也可以使用strace來調試系統錯誤。必須承認,strace的輸出不總是容易理解,但是很多輸出對大多數人來說是不重要的。你會慢慢學會從大量輸出中找到你可能需要的信息,像許可權錯誤,文件未找到之類的,那時strace就會成為一個有力的工具了。

閱讀全文

與linuxstrace命令相關的資料

熱點內容
程序員抽煙找靈感 瀏覽:767
老火湯pdf 瀏覽:224
少有人走的路與心靈對話pdf 瀏覽:205
兩單片機串口通信 瀏覽:801
程序員過試用期 瀏覽:108
演算法信息量不可計算 瀏覽:954
android淘寶防止反編譯 瀏覽:788
PIC單片機的內核寄存器 瀏覽:725
擠黑頭解壓視頻耳朵 瀏覽:771
可編程序控制器及其應用實訓總結 瀏覽:755
mcu單片機負載電路 瀏覽:57
解壓員工培訓游戲 瀏覽:283
局網怎麼設置伺服器地址 瀏覽:208
路由器如何關掉虛擬伺服器埠 瀏覽:845
Mac調整PDF 瀏覽:184
華為c6s雲伺服器能幹什麼 瀏覽:880
免費簡歷模板pdf 瀏覽:15
java查詢資料庫表 瀏覽:476
網站無法解析伺服器的dns地址 瀏覽:350
模型腳本反編譯教程 瀏覽:175