解讀:strace 系統(tǒng)調(diào)用跟蹤工具詳解與實(shí)戰(zhàn))
文檔教程【免費(fèi)下載鏈接】linux-commandLinux命令大全搜索工具內(nèi)容包含Linux命令手冊(cè)、詳解、學(xué)習(xí)、搜集。https://git.io/linux項(xiàng)目地址https://gitcode.com/GitHub_Trending/linux/linux-command點(diǎn)擊查看免費(fèi)下載本篇文章基于 linux-command 倉庫中的 strace 命令文檔 展開系統(tǒng)講解這一「集診斷、調(diào)試、統(tǒng)計(jì)于一體」的系統(tǒng)調(diào)用跟蹤工具從語法與全部選項(xiàng)入手通過追蹤系統(tǒng)調(diào)用、跟蹤信號(hào)傳遞、系統(tǒng)調(diào)用統(tǒng)計(jì)三個(gè)經(jīng)典實(shí)例再到分析 Oracle lgwr 進(jìn)程寫入行為的綜合實(shí)戰(zhàn)讓讀者掌握用 strace 定位故障、理解程序工作過程、量化系統(tǒng)調(diào)用開銷的完整方法論。strace 是什么系統(tǒng)調(diào)用與信號(hào)的雙重觀察窗口strace 命令是一個(gè)集診斷、調(diào)試、統(tǒng)計(jì)于一體的工具它通過對(duì)應(yīng)用的系統(tǒng)調(diào)用和信號(hào)傳遞進(jìn)行跟蹤幫助工程師解決問題或了解應(yīng)用的工作過程。需要明確的是strace 與專業(yè)的調(diào)試工具如 gdb定位不同它不是一個(gè)專業(yè)調(diào)試器不會(huì)提供斷點(diǎn)、單步執(zhí)行、變量查看等交互式調(diào)試能力而是以「旁觀者」的視角記錄程序與內(nèi)核之間的每一次交互。Linux 用戶態(tài)程序的一切行為最終都要通過系統(tǒng)調(diào)用syscall到達(dá)內(nèi)核例如讀寫文件、分配內(nèi)存、創(chuàng)建進(jìn)程、網(wǎng)絡(luò)通信同時(shí)進(jìn)程也會(huì)接收來自內(nèi)核或其他進(jìn)程的信號(hào)signal。strace 恰好把這兩類事件全部記錄下來并解析成人類可讀的文本這就構(gòu)成了觀察程序行為的兩個(gè)最佳窗口。在 linux-command 倉庫中strace 與幾個(gè)工具形成互補(bǔ)關(guān)系便于橫向?qū)Ρ壤斫鈒trace 命令文檔跟蹤進(jìn)程調(diào)用庫函數(shù)的情況與 strace 跟蹤系統(tǒng)調(diào)用恰好互補(bǔ)二者常搭配使用gdb 命令文檔功能強(qiáng)大的程序調(diào)試器支持?jǐn)帱c(diǎn)、單步、變量查看屬于真正的「專業(yè)調(diào)試器」strace 不與其競(jìng)爭(zhēng)。strace 最簡(jiǎn)單的用法就是執(zhí)行一個(gè)指定的命令在命令結(jié)束之后它也就退出。在命令執(zhí)行的過程中strace 會(huì)記錄并解析命令進(jìn)程的所有系統(tǒng)調(diào)用以及這個(gè)進(jìn)程所接收到的所有信號(hào)值。語法strace [ -dffhiqrtttTvxx ] [ -acolumn ] [ -eexpr ] ... [ -ofile ] [-ppid ] ... [ -sstrsize ] [ -uusername ] [ -Evarval ] ... [ -Evar ]... [command [ arg ... ] ] strace -c [ -eexpr ] ... [ -Ooverhead ] [ -Ssortby ] [ command [ arg... ] ]兩種語法形式的區(qū)別在于第一種是常規(guī)跟蹤模式直接跟蹤并實(shí)時(shí)輸出每個(gè)系統(tǒng)調(diào)用第二種固定以-c開頭進(jìn)入統(tǒng)計(jì)模式只輸出系統(tǒng)調(diào)用的匯總統(tǒng)計(jì)報(bào)表。-Ooverhead用于設(shè)置每個(gè)系統(tǒng)調(diào)用的開銷值微秒級(jí)以便-c統(tǒng)計(jì)時(shí)扣除該開銷得到更真實(shí)的耗時(shí)-Ssortby指定統(tǒng)計(jì)結(jié)果的排序字段如 time、calls、errors 等。選項(xiàng)詳解strace 的選項(xiàng)覆蓋面很廣下面是文檔中給出的完整選項(xiàng)清單-c 統(tǒng)計(jì)每一系統(tǒng)調(diào)用的所執(zhí)行的時(shí)間,次數(shù)和出錯(cuò)的次數(shù)等. -d 輸出strace關(guān)于標(biāo)準(zhǔn)錯(cuò)誤的調(diào)試信息. -f 跟蹤由fork調(diào)用所產(chǎn)生的子進(jìn)程. -ff 如果提供-o filename,則所有進(jìn)程的跟蹤結(jié)果輸出到相應(yīng)的filename.pid中,pid是各進(jìn)程的進(jìn)程號(hào). -F 嘗試跟蹤vfork調(diào)用.在-f時(shí),vfork不被跟蹤. -h 輸出簡(jiǎn)要的幫助信息. -i 輸出系統(tǒng)調(diào)用的入口指針. -q 禁止輸出關(guān)于脫離的消息. -r 打印出相對(duì)時(shí)間關(guān)于,,每一個(gè)系統(tǒng)調(diào)用. -t 在輸出中的每一行前加上時(shí)間信息. -tt 在輸出中的每一行前加上時(shí)間信息,微秒級(jí). -ttt 微秒級(jí)輸出,以秒了表示時(shí)間. -T 顯示每一調(diào)用所耗的時(shí)間. -v 輸出所有的系統(tǒng)調(diào)用.一些調(diào)用關(guān)于環(huán)境變量,狀態(tài),輸入輸出等調(diào)用由于使用頻繁,默認(rèn)不輸出. -V 輸出strace的版本信息. -x 以十六進(jìn)制形式輸出非標(biāo)準(zhǔn)字符串 -xx 所有字符串以十六進(jìn)制形式輸出. -a column 設(shè)置返回值的輸出位置.默認(rèn) 為40. -e expr 指定一個(gè)表達(dá)式,用來控制如何跟蹤.格式[qualifier][!]value1[,value2]... qualifier只能是 trace,abbrev,verbose,raw,signal,read,write其中之一.value是用來限定的符號(hào)或數(shù)字.默認(rèn)的 qualifier是 trace.感嘆號(hào)是否定符號(hào).例如:-eopen等價(jià)于 -e traceopen,表示只跟蹤open調(diào)用.而-etrace!open 表示跟蹤除了open以外的其他調(diào)用.有兩個(gè)特殊的符號(hào) all 和 none. 注意有些shell使用!來執(zhí)行歷史記錄里的命令,所以要使用\. -e traceset 只跟蹤指定的系統(tǒng) 調(diào)用.例如:-e traceopen,close,rean,write表示只跟蹤這四個(gè)系統(tǒng)調(diào)用.默認(rèn)的為setall. -e tracefile 只跟蹤有關(guān)文件操作的系統(tǒng)調(diào)用. -e traceprocess 只跟蹤有關(guān)進(jìn)程控制的系統(tǒng)調(diào)用. -e tracenetwork 跟蹤與網(wǎng)絡(luò)有關(guān)的所有系統(tǒng)調(diào)用. -e stracesignal 跟蹤所有與系統(tǒng)信號(hào)有關(guān)的 系統(tǒng)調(diào)用 -e traceipc 跟蹤所有與進(jìn)程通訊有關(guān)的系統(tǒng)調(diào)用 -e abbrevset 設(shè)定strace輸出的系統(tǒng)調(diào)用的結(jié)果集.-v 等與 abbrevnone.默認(rèn)為abbrevall. -e rawset 將指定的系統(tǒng)調(diào)用的參數(shù)以十六進(jìn)制顯示. -e signalset 指定跟蹤的系統(tǒng)信號(hào).默認(rèn)為all.如 signal!SIGIO(或者signal!io),表示不跟蹤SIGIO信號(hào). -e readset 輸出從指定文件中讀出 的數(shù)據(jù).例如: -e read3,5 -e writeset 輸出寫入到指定文件中的數(shù)據(jù). -o filename 將strace的輸出寫入文件filename -p pid 跟蹤指定的進(jìn)程pid. -s strsize 指定輸出的字符串的最大長(zhǎng)度.默認(rèn)為32.文件名一直全部輸出. -u username 以u(píng)sername的UID和GID執(zhí)行被跟蹤的命令面對(duì)這么多選項(xiàng)可以從四個(gè)維度來組織理解輸出控制類-o filename將輸出寫入文件對(duì)應(yīng)下文的「重定向輸出」-a column對(duì)齊返回值的輸出位置-s strsize限制字符串輸出長(zhǎng)度-q抑制附加消息-v展開所有調(diào)用細(xì)節(jié)如環(huán)境變量、狀態(tài)、輸入輸出等因調(diào)用頻繁默認(rèn)不展開的內(nèi)容-x/-xx控制非標(biāo)準(zhǔn)字符串的十六進(jìn)制顯示-i打印系統(tǒng)調(diào)用入口地址。進(jìn)程跟蹤類-f跟蹤 fork 出的子進(jìn)程守護(hù)進(jìn)程排障常用-ff配合-o時(shí)按filename.pid為每個(gè)進(jìn)程單獨(dú)輸出-F嘗試跟蹤 vfork-p pid掛接到已運(yùn)行進(jìn)程-u username以指定用戶身份運(yùn)行被跟蹤命令。時(shí)間類-r相對(duì)時(shí)間-t/-tt/-ttt三種時(shí)間戳精度-T單次調(diào)用耗時(shí)-c匯總統(tǒng)計(jì)-Ooverhead扣除系統(tǒng)調(diào)用開銷-Ssortby指定統(tǒng)計(jì)排序字段。診斷輔助類-d調(diào)試信息-h幫助-V版本信息。其中最重要的是-e expr其格式為[qualifier][!]value1[,value2]...。qualifier 只能是trace、abbrev、verbose、raw、signal、read、write之一默認(rèn)是tracevalue 是用于限定的符號(hào)或數(shù)字感嘆號(hào)表示否定。例如-e open等價(jià)于-e traceopen表示只跟蹤 open 調(diào)用而-e trace!open表示跟蹤除 open 以外的所有調(diào)用。另有all和none兩個(gè)特殊值。注意有些 shell 會(huì)用!執(zhí)行歷史命令因此在命令行中需要加反斜杠轉(zhuǎn)義。trace限定符還提供了幾個(gè)預(yù)置分類非常實(shí)用-e tracefile只跟蹤文件操作相關(guān)系統(tǒng)調(diào)用-e traceprocess只跟蹤進(jìn)程控制相關(guān)系統(tǒng)調(diào)用-e tracenetwork跟蹤所有網(wǎng)絡(luò)相關(guān)系統(tǒng)調(diào)用-e tracesignal跟蹤所有與信號(hào)相關(guān)的系統(tǒng)調(diào)用-e traceipc跟蹤所有與進(jìn)程間通信相關(guān)的系統(tǒng)調(diào)用。read/write限定符則用于輸出指定文件描述符上讀寫的數(shù)據(jù)內(nèi)容例如-e read3,5表示輸出從 fd 3、5 讀出的數(shù)據(jù)——這在分析協(xié)議交互時(shí)非常有用。實(shí)例一追蹤系統(tǒng)調(diào)用讀懂程序的一舉一動(dòng)做一個(gè)很簡(jiǎn)單的程序來演示 strace 的基本用法。C 語言代碼如下# filename test.c #include stdio.h int main() { int a; scanf(%d, a); printf(%09d\n, a); return 0; }程序邏輯極其簡(jiǎn)單從標(biāo)準(zhǔn)輸入讀一個(gè)整數(shù)再按 9 位寬度補(bǔ)零輸出。用gcc -o test test.c編譯得到可執(zhí)行文件 test然后用 strace 調(diào)用執(zhí)行strace ./test執(zhí)行期間程序會(huì)要求輸入一個(gè)整數(shù)輸入 99得到結(jié)果// 直接執(zhí)行test的結(jié)果 oracleorainst[orcl]:~ $./test // 執(zhí)行的結(jié)果 99 000000099 // 通過strace執(zhí)行test的結(jié)果 oracleorainst[orcl]:~ $strace ./test // strace的trace結(jié)果 execve(./test, [./test], [/* 41 vars */]) 0 uname({sysLinux, nodeorainst.desktop.mycompany.com, ...}) 0 brk(0) 0x8078000 fstat64(3, {st_modeS_IFREG|0644, st_size65900, ...}) 0 old_mmap(NULL, 65900, PROT_READ, MAP_PRIVATE, 3, 0) 0xbf5ef000 close(3) 0 open(/lib/tls/libc.so.6, O_RDONLY) 3 read(3, \177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\200X\1..., 512) 512 fstat64(3, {st_modeS_IFREG|0755, st_size1571692, ...}) 0 old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) 0xbf5ee000 old_mmap(NULL, 1275340, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) 0xa02000 old_mmap(0xb34000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x132000) 0xb34000 old_mmap(0xb37000, 9676, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) 0xb37000 close(3) 0 set_thread_area({entry_number:-1 - 6, base_addr:0xbf5ee740, limit:1048575, seg_32bit:1, contents:0, read_only_exec:0, limit_in_pages:1, seg_not_present:0, useable:1}) 0 munmap(0xbf5ef000, 65900) 0 fstat64(0, {st_modeS_IFCHR|0620, st_rdevmakedev(136, 0), ...}) 0 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) 0xbf5ff000 read(0, 99 99\n, 1024) 3 fstat64(1, {st_modeS_IFCHR|0620, st_rdevmakedev(136, 0), ...}) 0 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) 0xbf5fe000 write(1, 000000099\n, 10000000099 ) 10 munmap(0xbf5fe000, 4096) 0 exit_group(0) ?從 trace 結(jié)構(gòu)可以看到程序完整的工作過程系統(tǒng)首先調(diào)用execve開始一個(gè)新的進(jìn)程接著進(jìn)行環(huán)境初始化——uname獲取內(nèi)核信息、brk調(diào)整堆、一系列old_mmap映射動(dòng)態(tài)庫libc.so.6代碼段與數(shù)據(jù)段、set_thread_area設(shè)置線程本地存儲(chǔ)最后程序停頓在read(0, ...)上——這對(duì)應(yīng)scanf等待輸入。輸入 99 后程序調(diào)用write將格式化后的數(shù)值000000099輸出到屏幕fd 1最后調(diào)用exit_group退出進(jìn)程完成整個(gè)執(zhí)行過程。這里值得留意的是每個(gè)系統(tǒng)調(diào)用末尾的 0、 3、 10它們是調(diào)用的返回值例如read(0, 99\n, 1024) 3表示從標(biāo)準(zhǔn)輸入實(shí)際讀到了 3 個(gè)字節(jié)write(1, 000000099\n, ...) 10表示寫出了 10 個(gè)字節(jié)。返回值是 strace 輸出中最關(guān)鍵的信息之一排障時(shí)經(jīng)常據(jù)此判斷調(diào)用是否失敗負(fù)數(shù)即出錯(cuò)。實(shí)例二跟蹤信號(hào)傳遞觀察進(jìn)程如何被終止仍使用上面的 test 程序觀察進(jìn)程接收信號(hào)的情況。先執(zhí)行strace ./test等到等待輸入的畫面時(shí)不要輸入任何內(nèi)容然后打開另一個(gè)終端窗口輸入killall test可以看到程序隨即退出最后的 trace 結(jié)果如下oracleorainst[orcl]:~ $strace ./test execve(./test, [./test], [/* 41 vars */]) 0 uname({sysLinux, nodeorainst.desktop.mycompany.com, ...}) 0 brk(0) 0x9ae2000 old_mmap(NULL, 65900, PROT_READ, MAP_PRIVATE, 3, 0) 0xbf5ef000 close(3) 0 open(/lib/tls/libc.so.6, O_RDONLY) 3 read(3, \177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\200X\1..., 512) 512 fstat64(3, {st_modeS_IFREG|0755, st_size1571692, ...}) 0 old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) 0xbf5ee000 old_mmap(NULL, 1275340, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) 0x2e9000 old_mmap(0x41b000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x132000) 0x41b000 old_mmap(0x41e000, 9676, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) 0x41e000 close(3) 0 set_thread_area({entry_number:-1 - 6, base_addr:0xbf5ee740, limit:1048575, seg_32bit:1, contents:0, read_only_exec:0, limit_in_pages:1, seg_not_present:0, useable:1}) 0 munmap(0xbf5ef000, 65900) 0 fstat64(0, {st_modeS_IFCHR|0620, st_rdevmakedev(136, 0), ...}) 0 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) 0xbf5ff000 read(0, 0xbf5ff000, 1024) ? ERESTARTSYS (To be restarted) --- SIGTERM (Terminated) 0 (0) --- killed by SIGTERM 這次的關(guān)鍵變化在最后三行阻塞在read(0, ...)上的進(jìn)程收到 SIGTERM 信號(hào)read 系統(tǒng)調(diào)用被中斷返回? ERESTARTSYS (To be restarted)該返回值表示系統(tǒng)調(diào)用將被重啟緊接著 strace 打印出--- SIGTERM (Terminated) 0 (0) ---標(biāo)記信號(hào)到達(dá)并以 killed by SIGTERM 明確告知 test 進(jìn)程是被 SIGTERM 信號(hào)殺死的。killall命令默認(rèn)發(fā)送的正是 SIGTERM可參考倉庫中 killall 命令文檔它把「按名稱查找進(jìn)程 發(fā)送信號(hào)」兩步合并為一步。這一實(shí)例展示了 strace 的典型排障用法當(dāng)程序「莫名其妙」退出時(shí)strace 能明確告訴你是被哪個(gè)信號(hào)終止的——這在排查 OOM Killer、外部監(jiān)控腳本誤殺、服務(wù)重啟等場(chǎng)景中尤其有用。實(shí)例三系統(tǒng)調(diào)用統(tǒng)計(jì)量化程序行為strace 不光能追蹤系統(tǒng)調(diào)用通過-c參數(shù)它還能將進(jìn)程所有的系統(tǒng)調(diào)用做一個(gè)統(tǒng)計(jì)分析。執(zhí)行帶-c參數(shù)的 stracestrace -c ./test得到的統(tǒng)計(jì)結(jié)果oracleorainst[orcl]:~ $strace -c ./test execve(./test, [./test], [/* 41 vars */]) 0 % time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ---------------- 45.90 0.000140 5 27 25 open 34.43 0.000105 4 24 21 stat64 7.54 0.000023 5 5 old_mmap 2.62 0.000008 8 1 munmap 1.97 0.000006 6 1 uname 1.97 0.000006 2 3 fstat64 1.64 0.000005 3 2 1 read 1.31 0.000004 2 2 close 0.98 0.000003 3 1 brk 0.98 0.000003 3 1 mmap2 0.66 0.000002 2 1 set_thread_area ------ ----------- ----------- --------- --------- ---------------- 100.00 0.000305 68 47 total統(tǒng)計(jì)表清晰地揭示了程序的行為特征open被調(diào)用了 27 次卻出現(xiàn) 25 次錯(cuò)誤error 列stat64調(diào)用 24 次出現(xiàn) 21 次錯(cuò)誤——這是因?yàn)閯?dòng)態(tài)鏈接器在搜索共享庫時(shí)會(huì)對(duì)多個(gè)候選路徑逐一open/stat64找不到就返回錯(cuò)誤直到命中正確的路徑這是正?,F(xiàn)象而非故障。% time列展示每個(gè)系統(tǒng)調(diào)用的耗時(shí)占比seconds是該類調(diào)用的累計(jì)耗時(shí)usecs/call是單次調(diào)用平均耗時(shí)calls是調(diào)用次數(shù)errors是出錯(cuò)次數(shù)。末尾的total行給出全局匯總本次運(yùn)行共 68 次調(diào)用、47 次出錯(cuò)、總耗時(shí) 0.000305 秒。這個(gè)功能對(duì)分析程序性能熱點(diǎn)極有價(jià)值哪類系統(tǒng)調(diào)用最耗時(shí)、出錯(cuò)最頻繁一眼即知從而為優(yōu)化方向如減少文件系統(tǒng)訪問、增加緩存、合并小寫入提供數(shù)據(jù)支撐。常用參數(shù)實(shí)戰(zhàn)除了-cstrace 還提供了其他常用參數(shù)便于按需獲取信息。重定向輸出參數(shù)-o用于將 strace 的結(jié)果輸出到文件中。如果不指定-o默認(rèn)輸出設(shè)備是 STDERR也就是說-o filename和2filename的結(jié)果是一樣的# 這兩個(gè)命令都是將strace結(jié)果輸出到文件test.txt中 strace -c -o test.txt ./test strace -c ./test 2test.txt理解這一點(diǎn)的實(shí)際價(jià)值在于strace 結(jié)果默認(rèn)走 stderr 而非 stdout因此既可以用-o讓工具自己管理輸出文件也可以借助 shell 的重定向機(jī)制把輸出導(dǎo)入任意位置例如配合grep過濾、tee同時(shí)查看和保存。跟蹤產(chǎn)生大量輸出時(shí)務(wù)必使用文件保存避免終端刷屏影響觀察。對(duì)系統(tǒng)調(diào)用進(jìn)行計(jì)時(shí)strace 可以使用-T參數(shù)將每個(gè)系統(tǒng)調(diào)用所花費(fèi)的時(shí)間打印出來每個(gè)調(diào)用的時(shí)間開銷顯示在調(diào)用行最右邊的尖括號(hào)內(nèi)oracleorainst[orcl]:~ $strace -T ./test // 這里只摘錄部分結(jié)果 read(0, 1 1\n, 1024) 2 2.673455 fstat64(1, {st_modeS_IFCHR|0620, st_rdevmakedev(136, 0), ...}) 0 0.000014 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) 0xbf5fe000 0.000017 write(1, 000000001\n, 10000000001 ) 10 0.000016 munmap(0xbf5fe000, 4096) 0 0.000020 exit_group(0) ?注意read調(diào)用耗時(shí) 2.673455 秒——這是它阻塞等待鍵盤輸入的時(shí)間與程序執(zhí)行邏輯一致而后續(xù)調(diào)用都是微秒級(jí)。這一參數(shù)把「哪次調(diào)用慢」精確到單個(gè)系統(tǒng)調(diào)用級(jí)別是定位 IO 瓶頸、鎖等待、網(wǎng)絡(luò)阻塞的利器。系統(tǒng)調(diào)用的時(shí)間strace 會(huì)將每次系統(tǒng)調(diào)用的發(fā)生時(shí)間記錄下來使用-t/-tt/-ttt三個(gè)參數(shù)即可看到效果參數(shù)名輸出樣式說明-t10:33:04 exit_group(0)輸出結(jié)果精確到秒-tt10:33:48.159682 exit_group(0)輸出結(jié)果精確到微秒-ttt1262169244.788478 exit_group(0)精確到微秒且時(shí)間表示為 Unix 時(shí)間戳三種精度的選擇取決于分析粒度粗看調(diào)用序列用-t足夠分析毫秒級(jí)延遲或調(diào)用頻率用-tt需要與其他日志時(shí)間戳如應(yīng)用日志、數(shù)據(jù)庫 trace 文件做跨源對(duì)齊時(shí)-ttt輸出的 Unix 時(shí)間戳最方便計(jì)算時(shí)間差。截?cái)噍敵?s參數(shù)用于指定 trace 結(jié)果每一行輸出的字符串長(zhǎng)度。下面看看對(duì) test 程序中-s參數(shù)的影響指定-s 20然后在 read 時(shí)輸入一個(gè)超過 20 個(gè)字符的數(shù)字串strace -s 20 ./test read(0, 2222222222222222222222222 // 我們輸入的2一共有25個(gè) 22222222222222222222..., 1024) 26 // 而我們看到的結(jié)果中2只有20個(gè)默認(rèn)情況下字符串最多顯示 32 個(gè)字符文件名除外文件名一直全部輸出。當(dāng)關(guān)心調(diào)用參數(shù)中的大塊數(shù)據(jù)如完整的 SQL 文本、協(xié)議報(bào)文時(shí)就需要調(diào)大-s反之當(dāng)輸出中夾雜大量二進(jìn)制數(shù)據(jù)影響閱讀時(shí)可以調(diào)小-s讓輸出更清爽。跟蹤一個(gè)現(xiàn)有的進(jìn)程strace 不僅能自己初始化一個(gè)進(jìn)程進(jìn)行跟蹤還能掛接到現(xiàn)有進(jìn)程上參數(shù)-p就是起這個(gè)作用的strace -p pid掛接運(yùn)行中的進(jìn)程是生產(chǎn)環(huán)境排障的典型姿勢(shì)進(jìn)程已經(jīng)出現(xiàn)異??ㄋ馈⒏哓?fù)載、句柄泄漏時(shí)才介入無需重啟進(jìn)程直接觀察其當(dāng)前行為。掛接后按 CtrlC 即可停止跟蹤并恢復(fù)進(jìn)程正常運(yùn)行。綜合實(shí)戰(zhàn)strace 分析 Oracle lgwr 進(jìn)程前面介紹了不少功能和參數(shù)下面來看一個(gè)實(shí)用的綜合案例研究 Oracle 的 lgwrLog Writer日志寫進(jìn)程進(jìn)程驗(yàn)證它是否像文檔所述那樣每 3 秒寫一次 log 文件??紤]到 lgwr 寫日志的觸發(fā)條件比較多需要找一個(gè)空閑的 Oracle 實(shí)例做這個(gè)實(shí)驗(yàn)。第一步獲取 lgwr 進(jìn)程的 PIDps -ef|grep lgwr oracle 5912 1 0 Nov12 ? 00:14:56 ora_lgwr_orcl得到 lgwr 的 PID 是 5912ps -ef | grep的常規(guī)找進(jìn)程方式可參考倉庫中 ps 命令文檔。啟動(dòng) strace將跟蹤結(jié)果輸出到 lgwr.txt 文件中strace -tt -s 10 -o lgwr.txt -p 5912這里綜合使用了三個(gè)參數(shù)-tt輸出微秒級(jí)時(shí)間戳用于精確觀察寫入間隔、-s 10截?cái)嘧址敵鰈gwr 寫入的數(shù)據(jù)塊很大只關(guān)心前 10 個(gè)字符即可、-o lgwr.txt將結(jié)果寫入文件避免長(zhǎng)時(shí)間跟蹤刷屏。過一會(huì)兒停止 strace然后查看結(jié)果。由于輸出較多為了方便只查看 Oracle 寫入 log 文件時(shí)用到的 pwrite 函數(shù)調(diào)用grep pwrite\(20 lgwr.txt為什么 grep 時(shí)用pwrite(20呢因?yàn)楫?dāng)前機(jī)器打開的 log 文件句柄編號(hào)從 2 開始。具體查找方法是先找出當(dāng)前活動(dòng)的日志文件都有哪些在 SQL*Plus 中執(zhí)行select member, v$log.status from v$log, v$logfile where v$log.group#v$logfile.group#;得到MEMBER STATUS -------------------------------------------------- ---------------- /db/databases/orcl/redo-01-a/redo-t01-g03-m1.log INACTIVE /db/databases/orcl/redo-03-a/redo-t01-g03-m2.log INACTIVE /db/databases/orcl/redo-02-a/redo-t01-g02-m1.log CURRENT /db/databases/orcl/redo-04-a/redo-t01-g02-m2.log CURRENT /db/databases/orcl/redo-01-a/redo-t01-g01-m1.log INACTIVE /db/databases/orcl/redo-03-a/redo-t01-g01-m2.log INACTIVE /db/databases/orcl/redo-02-a/redo-t01-g04-m1.log INACTIVE /db/databases/orcl/redo-04-a/redo-t01-g04-m2.log INACTIVE然后到 /proc 中查看該進(jìn)程打開的文件句柄ll /proc/.5912/fd/得到lrwx------ 1 oracle dba 64 Dec 30 10:55 18 - /db/databases/orcl/redo-01-a/redo-t01-g01-m1.log lrwx------ 1 oracle dba 64 Dec 30 10:55 19 - /db/databases/orcl/redo-03-a/redo-t01-g01-m2.log lrwx------ 1 oracle dba 64 Dec 30 10:55 20 - /db/databases/orcl/redo-02-a/redo-t01-g02-m1.log lrwx------ 1 oracle dba 64 Dec 30 10:55 21 - /db/databases/orcl/redo-04-a/redo-t01-g02-m2.log lrwx------ 1 oracle dba 64 Dec 30 10:55 22 - /db/databases/orcl/redo-01-a/redo-t01-g03-m1.log lrwx------ 1 oracle dba 64 Dec 30 10:55 23 - /db/databases/orcl/redo-03-a/redo-t01-g03-m2.log lrwx------ 1 oracle dba 64 Dec 30 10:55 24 - /db/databases/orcl/redo-02-a/redo-t01-g04-m1.log lrwx------ 1 oracle dba 64 Dec 30 10:55 25 - /db/databases/orcl/redo-04-a/redo-t01-g04-m2.log對(duì)照 SQL 查詢結(jié)果可知狀態(tài)為 CURRENT 的兩個(gè)活動(dòng)日志文件group 2 的兩個(gè)成員對(duì)應(yīng)的句柄是 20 和 21。至此grep pwrite\(20 lgwr.txt的過濾條件就有了依據(jù)。得到的結(jié)果如下11:13:55.603245 pwrite(20, \1\\0\0J!..., 1536, 4363264) 1536 11:13:55.603569 pwrite(21, \1\\0\0M!..., 1536, 4363264) 1536 11:13:55.606888 pwrite(20, \1\\0\0M!..., 1536, 4364800) 1536 11:13:55.607172 pwrite(21, \1\\0\0M!..., 1536, 4364800) 1536 11:13:55.607934 pwrite(20, \1\\0\0P!..., 1536, 4366336) 1536 11:13:55.608199 pwrite(21, \1\\0\0P!..., 1536, 4366336) 1536 11:13:55.610260 pwrite(20, \1\\0\0S!..., 1536, 4367872) 1536 11:13:55.610530 pwrite(21, \1\\0\0S!..., 1536, 4367872) 1536 11:14:00.602446 pwrite(20, \1\\0\0V!..., 1536, 4369408) 1536 11:14:00.602750 pwrite(21, \1\\0\0V!..., 1536, 4369408) 1536 11:14:00.606386 pwrite(20, \1\\0\0Y!..., 1536, 4370944) 1536 11:14:00.606676 pwrite(21, \1\\0\0Y!..., 1536, 4370944) 1536 11:14:00.607900 pwrite(20, \1\\0\0\\..., 1024, 4372480) 1024 11:14:00.608161 pwrite(21, \1\\0\0\\..., 1024, 4372480) 1024 11:14:00.608816 pwrite(20, \1\\0\0^!..., 1024, 4373504) 1024 11:14:00.609071 pwrite(21, \1\\0\0^!..., 1024, 4373504) 1024 11:14:00.611142 pwrite(20, \1\\0\0!..., 1536, 4374528) 1536 11:14:00.611454 pwrite(21, \1\\0\0!..., 1536, 4374528) 1536 11:14:05.602804 pwrite(20, \1\\0\0c!..., 1024, 4376064) 1024 11:14:05.603119 pwrite(21, \1\\0\0c!..., 1024, 4376064) 1024 11:14:05.607731 pwrite(20, \1\\0\0e!..., 1024, 4377088) 1024 11:14:05.608020 pwrite(21, \1\\0\0e!..., 1024, 4377088) 1024 11:14:05.608690 pwrite(20, \1\\0\0g!..., 1024, 4378112) 1024 11:14:05.608962 pwrite(21, \1\\0\0g!..., 1024, 4378112) 1024 11:14:05.611022 pwrite(20, \1\\0\0i!..., 1536, 4379136) 1536 11:14:05.611283 pwrite(21, \1\\0\0i!..., 1536, 4379136) 1536從輸出可以清楚讀出11:13:55 有一組寫操作隨后 11:14:00、11:14:05 又各出現(xiàn)一組——兩次寫日志的時(shí)間間隔正好是 5 秒。每組寫操作中l(wèi)gwr 對(duì)成員文件 20 和 21 交替以pwrite寫入 1024/1536 字節(jié)的數(shù)據(jù)塊pwrite 的第三個(gè)參數(shù)是寫入長(zhǎng)度第四個(gè)參數(shù)是文件偏移返回值等于寫入長(zhǎng)度表示寫入成功。這驗(yàn)證了 lgwr 的周期性寫入行為也完整展示了一個(gè)「strace 掛接生產(chǎn)進(jìn)程 SQL 查詢定位文件 /proc 確認(rèn)句柄 定向 grep 過濾」的組合排障方法論。小結(jié)何時(shí)使用 strace回顧全文strace 的典型使用場(chǎng)景可以歸納為四類程序「憑空」退出或行為異常用strace或strace -f跟蹤子進(jìn)程觀察卡在哪個(gè)系統(tǒng)調(diào)用、收到什么信號(hào)參考實(shí)例二的 SIGTERM 定位法性能熱點(diǎn)定位用-c得到系統(tǒng)調(diào)用統(tǒng)計(jì)表或-T定位單次慢調(diào)用參考實(shí)例三與常用參數(shù)一節(jié)理解陌生程序的內(nèi)部工作過程用默認(rèn)跟蹤模式完整記錄其啟動(dòng)、初始化、主循環(huán)的每一步系統(tǒng)調(diào)用參考實(shí)例一生產(chǎn)環(huán)境診斷運(yùn)行中的進(jìn)程用-p掛接 -o落盤 -tt精確時(shí)間戳配合 grep 過濾感興趣的系統(tǒng)調(diào)用參考綜合實(shí)戰(zhàn)中的 lgwr 案例。掌握 strace 后Linux 上「程序做了什么」不再是一個(gè)黑盒。它和 ltrace 命令文檔庫函數(shù)層、gdb 命令文檔交互調(diào)試層共同構(gòu)成了從系統(tǒng)調(diào)用到用戶態(tài)代碼的完整觀察鏈條是 Linux 工程師排障工具箱中不可或缺的一環(huán)。贊分享文檔教程【免費(fèi)下載鏈接】linux-commandLinux命令大全搜索工具內(nèi)容包含Linux命令手冊(cè)、詳解、學(xué)習(xí)、搜集。https://git.io/linux項(xiàng)目地址https://gitcode.com/GitHub_Trending/linux/linux-command點(diǎn)擊查看免費(fèi)下載相關(guān)推薦MATHC向量操作完全指南從基礎(chǔ)到高級(jí)的2D/3D向量處理MATHC向量操作完全指南從基礎(chǔ)到高級(jí)的2D/3D向量處理 MATHC是一個(gè)純C語言編寫的輕量級(jí)數(shù)學(xué)庫專注于2D和3D向量處理為游戲開發(fā)、圖形編程等場(chǎng)景提終極指南如何在xv6-riscv中實(shí)現(xiàn)系統(tǒng)調(diào)用跟蹤與strace工具功能終極指南如何在xv6 riscv中實(shí)現(xiàn)系統(tǒng)調(diào)用跟蹤與strace工具功能 xv6 riscv是一個(gè)基于RISC V架構(gòu)的教學(xué)操作系統(tǒng)通過學(xué)習(xí)它可以深入理解操操作系統(tǒng)嵌入式img2threejs 細(xì)節(jié)清單Detail Inventory實(shí)戰(zhàn)指南把參考圖中的身份細(xì)節(jié)變成可門禁的結(jié)構(gòu)化數(shù)據(jù)img2threejs 細(xì)節(jié)清單Detail Inventory實(shí)戰(zhàn)指南把參考圖中的身份細(xì)節(jié)變成可門禁的結(jié)構(gòu)化數(shù)據(jù) 導(dǎo)讀 detailInventoryAI 技能3D渲染代碼生成創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考