如何使用 strace 追蹤程序的系統呼叫

Strace 是一款 Linux 命令列工具,它藉助 ptrace() 系統呼叫即時攔截系統呼叫與訊號,能夠精確展示一個程序在伺服器上的實際行為。因此,strace 是除錯與故障排除、效能調校以及安全分析中的重要工具。你可以使用 strace 來追蹤系統呼叫,從基礎命令到進階輸出管理都能涵蓋。當你在 Linux 伺服器上除錯應用程式時,strace 能顯示每一次檔案開啟、網路讀取與記憶體配置。這種可見性讓排障從「猜測」變成「精準診斷」。你將學會如何在不重新啟動服務的情況下,對正在執行的服務進行系統呼叫追蹤。
如何使用 strace 追蹤系統呼叫
追蹤某個命令發起的系統呼叫
使用 strace 追蹤系統呼叫最簡單的方法,就是直接透過它來執行目標命令。你只需輸入 strace,後面接上你想觀察的命令。例如,strace ls -l 會在執行 ls 命令的同時,擷取它發起的每一次系統呼叫。該工具會記錄程式與 Linux 核心之間的每一次互動。你可以看到檔案開啟、目錄讀取、記憶體映射以及程序結束等操作。這種方式非常適合那些生命週期較短、希望立即看到結果的命令。
其基本語法如下:strace /path/to/program。你可以用這種方式追蹤任何可執行檔。執行該命令後,strace 會將目標程式作為子程序啟動,並攔截程式送給核心的每一個請求。輸出中的每一行都會顯示系統呼叫名稱、參數以及回傳值。這些輸出能幫助你完整了解程式的執行行為。你可以藉此發現缺失檔案、權限錯誤或意料之外的網路連線。命令會持續執行,直到正常結束或發生崩潰。之後,strace 會在終端機中列印最終結果摘要。
這種方法最適合用於除錯腳本、測試新軟體,或理解某個工具的內部行為。你還可以搭配其他選項對結果進行篩選。例如,你可能只想追蹤與檔案相關的操作,或只關注網路活動。關鍵在於,你可以從頭到尾掌控整個執行過程,無需猜測程式每一步做了什麼。
附加到正在執行的程序
在伺服器環境中,你經常需要診斷一個已經在執行的服務,而不能簡單地重新啟動它後再進行追蹤。這種情況下,你可以使用 -p 選項附加到一個正在執行的程序。語法是 strace -p PID,其中 PID 表示程序 ID。你必須先知道要檢查的程序號,可以透過 ps 或 pgrep 等命令來取得。例如,pgrep nginx 會回傳每個 nginx 工作程序的 PID。
一旦附加成功,strace 就會從那一刻開始擷取該程序發起的所有系統呼叫。被追蹤的程序會繼續正常執行,不會中斷現有工作,也不會造成停機。這項能力對於生產環境伺服器尤其寶貴。你可以觀察 Web 伺服器如何處理請求、資料庫如何執行查詢,或應用程式如何寫入日誌。該工具依賴 ptrace() 系統呼叫來附加到另一個程序。在 Linux 中,只要你具備適當權限,通常是 root 使用者或與目標程序相同的使用者,就可以執行此操作。
你也可以分別附加到多個特定程序上一一追蹤。如果某個服務會產生多個 worker 程序,你可能需要分別附加到每一個程序。此時,-f 選項就很有幫助,因為它可以自動追蹤子程序。不過,如果你只需要觀察某一個程序,strace -p PID 就能提供足夠聚焦的可見性。你可以即時看到系統呼叫發生的整個過程。觀察結束後,按下 Ctrl+C 即可分離。目標程序會繼續執行,不受影響。這種非侵入式方式讓 strace 成為繁忙伺服器上的強大診斷工具。你可以在不影響業務運作的前提下,洞察即時行為。
Linux 中 strace 的核心選項
追蹤子程序
許多伺服器應用並不是單程序執行的。像 Apache 或 Nginx 這樣的 Web 伺服器會建立多個 worker 程序來處理並行請求。資料庫也可能 fork 出輔助程序來執行背景任務。如果你只追蹤主程序,就會錯過這些 worker 中發生的大量活動。-f 選項正是為了解決這個問題而設計的。它會告訴 strace 追蹤由 fork、clone 或 vfork 建立的子程序。一旦有新程序出現,strace 就會自動開始對其進行追蹤。
你可以這樣使用該選項:strace -f -p PID。該工具會先附加到主程序,然後繼續觀察它建立的每一個子程序。這項能力對於追蹤會衍生 worker 的伺服器程式至關重要。如果不加 -f,你只能看到父程序的系統呼叫;加上它後,你就能獲得整個程序樹的完整視圖。輸出中會為每次系統呼叫標註發起該呼叫的 PID,因此你可以輕鬆區分主程序與其子程序。
以 PHP-FPM 伺服器處理 Web 請求為例:主程序接收連線,並將任務分配給 worker 程序。如果不使用 -f,你看到的只有主程序的活動;而加入 -f 後,你就能精確看到每個 worker 是如何處理每一個請求的。你可以看到跨 worker 的檔案讀取、資料庫查詢與網路操作。這種可見性有助於你識別特定 worker 程序中的瓶頸或錯誤。
篩選系統呼叫
繁忙的伺服器每秒會產生成千上萬次系統呼叫。如果全部追蹤,輸出量會極其龐大,反而掩蓋你真正需要的資訊。-e trace= 選項可以將追蹤範圍限定在特定的系統呼叫上。你只需指定自己感興趣的呼叫,strace 就會忽略其他內容。例如,strace -e trace=open,read,write 只會擷取檔案操作與資料傳輸相關的系統呼叫。這種聚焦式方法能有效減少雜訊,凸顯關鍵行為。
你也可以按類別而不是單個呼叫來篩選。%process 類別包含 fork、wait 與 exec 等程序管理相關呼叫。使用 -e trace=%process 可以查看一個程式是如何建立與管理子程序的。%signal 類別涵蓋 kill 與 sigaction 等與訊號相關的呼叫,這有助於你除錯訊號處理問題。%pure 類別則包含那些總是成功且不帶參數的系統呼叫,例如 getpid。這類呼叫通常很少成為問題根源,因此篩選掉它們能減少輸出干擾。
將這些篩選器與 -f 結合使用,可以實現非常精細的控制。例如,你可以只追蹤所有子程序中的網路相關呼叫。命令 strace -f -e trace=network -p PID 會擷取每個 worker 的 socket 操作。這種定向追蹤方式非常適合用於診斷連線問題或效能異常。
如果你需要保存結果,可使用 -o 選項並指定檔名。這樣,追蹤輸出就會寫入檔案,而不是顯示在終端機中。命令 strace -o trace.log -p PID 會將所有擷取到的資料寫入 trace.log。你可以稍後再查看這個檔案,或分享給同事。將輸出寫入檔案還能避免追蹤資訊與終端機中的正常顯示內容混在一起。對於長時間執行的追蹤任務,你可以把追蹤結果重新導向到文字檔中,在分離後再進行分析。這種方法既能保持終端機整潔,也能保留資料以便深入檢查。-o 選項可以與所有其他篩選器搭配使用,因此你也可以只保存自己真正關心的那些系統呼叫。
使用 strace 分析效能
系統呼叫摘要
你還可以藉助 -c 選項,將 strace 變成一個效能分析工具。這個參數不會輸出逐行追蹤結果,而是產生一張摘要表。表格會顯示每種系統呼叫的次數、錯誤數量以及總耗時。這樣你就能快速看出哪些操作佔據了主要開銷,而無需閱讀成千上萬行細節。
執行 strace -c -p PID 即可附加到一個正在執行的服務並開始蒐集資料。讓追蹤執行幾秒鐘或幾分鐘後,按下 Ctrl+C,strace 就會在終端機中列印摘要表。該表通常按耗時排序。你可能會發現 read 操作佔據了 80% 的時間,或者看到 poll 呼叫佔主導地位,這通常表示程序處於閒置等待狀態。這些資訊能幫助你把最佳化精力集中到真正的問題區域。
摘要表還會顯示每種系統呼叫的錯誤計數。如果 open 或 connect 的錯誤數很高,往往表示存在設定問題。看到這種模式後,你就可以進一步調查這些失敗呼叫。-c 選項也可以與 -f 一起使用,從而把子程序納入統計摘要中。這樣,你就能對整個程序樹進行效能分析,從所有 worker 的角度獲得完整的效能輪廓。
時間戳與延遲
有時,你需要知道每一次系統呼叫發生的具體時間。-t 選項會為輸出中的每一行加入時間戳。每個時間戳都顯示當天時間,精確到秒。這樣你就可以把系統呼叫與外部事件對應起來。例如,你可以把一次緩慢的資料庫查詢與某個特定的 read 呼叫關聯起來。-tt 選項則會進一步提升到微秒級精度,有助於揭示相關系統呼叫之間的短暫延遲。
-r 選項提供相對時間戳。每一行都會顯示距離上一次系統呼叫經過了多長時間。這種格式非常適合用來發現操作之間的延遲。你可以清楚看到某次 write 呼叫與對應的 read 呼叫之間是否存在較長間隔。這樣的間隔可能意味著網路延遲,也可能表示磁碟 I/O 變慢。相對時間戳會讓這些問題一目了然。
你還可以把時間戳與篩選器結合起來,將注意力集中到特定行為上。例如,只追蹤網路相關呼叫並加入 -tt 以取得微秒級精度。這樣,你就能準確看到連線延遲具體發生在哪一步。你也可以把這些輸出保存到檔案中,以便後續分析。保存後的檔案會保留時間戳,從而完整保留時序資訊。這種做法也有助於團隊記錄效能問題,並在修改後比較不同時間點的追蹤結果,以評估最佳化效果。
在繁忙伺服器上管理大量輸出
壓縮追蹤輸出
高流量伺服器在追蹤期間會產生海量資料。每一次檔案讀取、網路封包處理以及記憶體操作,都會產生一行文字。當你追蹤繁忙的 Web 伺服器或資料庫時,磁碟空間可能很快就被耗盡。-C 選項可以解決這個問題,它能夠在寫出追蹤結果時即時進行壓縮。這個參數通常與 -o 搭配使用,把壓縮後的資料直接寫入檔案。最終你得到的是一個 .gz 檔案,而不是一般文字檔。這種方式能夠顯著減少儲存空間占用。
例如,如果你追蹤一個每秒處理數百個請求的程序,不壓縮的話,幾分鐘內就可能產生數 GB 的資料;而啟用 -C 後,輸出體積會明顯縮小。壓縮是在 strace 擷取每一個系統呼叫時即時完成的,因此你無需在事後再手動壓縮檔案。對於生產伺服器上磁碟空間有限的場景,這項功能尤其實用。你可以進行更長時間的追蹤,而不必過度擔心檔案系統被寫滿。
輪替長時間執行的追蹤檔案
長時間執行的追蹤任務還會帶來另一個挑戰。你可能需要連續監控某項服務數小時,才能捕捉到一個偶發性問題。若只寫入單一輸出檔案,它會持續增大,逐漸變得難以管理。你可以將 -o 與 logrotate 或 split 等外部工具搭配使用,以處理這種持續成長的檔案。logrotate 工具可以依照檔案大小或時間間隔自動輪替日誌檔。你可以將其設定為在目前追蹤檔案達到某個條件後自動重新命名,並開始寫入新檔案。這樣既能讓單一檔案維持在可管理範圍內,也能保留歷史資料。
-ff 選項則進一步增強了控制能力。將它與 -o 組合使用時,strace 會為每個子程序分別建立一個輸出檔案。也就是說,每個 worker 程序都會寫入自己的檔案。你可以分別對這些檔案進行輪替管理。這種方式更容易幫助你隔離特定 worker 中的問題。比如,你可能會發現某一個 worker 持續報錯,而其他 worker 都運作正常。分離的檔案會讓這種模式更加清晰。
你還應牢記,追蹤本身會給系統帶來額外開銷。每一個被擷取的系統呼叫都需要額外處理時間。在繁忙伺服器上,這種開銷可能會明顯拖慢被追蹤程序。因此,應該使用 -e trace= 篩選器來減少擷取的資料量,只關注你真正需要的系統呼叫。這樣做既能降低效能影響,也能減少輸出體積,讓你的伺服器在蒐集診斷資訊的同時盡可能保持回應能力。
現在你已經了解如何使用 strace 在 Linux 伺服器上追蹤系統呼叫:從追蹤簡單命令,到深入進行效能分析。這個 Linux 工具能夠擷取訊號以及程序發出的每一個核心請求。像 -f、-e trace= 與 -c 這樣的選項,可以讓你的追蹤輸出更加聚焦,也能避免海量原始輸出淹沒你真正需要的那個關鍵細節。
建議先在測試機器上練習。在生產環境中,請記住 strace 會拖慢目標程序,因此應盡量使用篩選器縮小範圍,並在觀察完成後及時分離。
只有在確有必要時,才附加到一個已經在執行的程序上。只要使用得當,這個 Linux 工具就會成為你最可靠的診斷利器之一。
常見問題
strace 在 Linux 伺服器上究竟能做什麼?
Strace 會攔截程式向 Linux 核心發起的每一次系統呼叫。它能即時展示檔案開啟、網路讀取與記憶體操作等行為。這種可見性能幫助你診斷錯誤、找出瓶頸,並在無需猜測的前提下理解應用程式的執行方式。你可以使用 strace 追蹤系統呼叫,用於除錯或效能分析。
如何把 strace 附加到一個正在執行的服務上?
你可以使用帶有程序 ID 的 -p 選項。首先,使用 ps 或 pgrep 找到目標程序的 PID。然後執行 strace -p PID。該工具會立刻附加到該程序並開始擷取它的系統呼叫。按下 Ctrl+C 即可分離。這種方法適用於任何 Linux 發行版。
strace 會影響伺服器效能嗎?
會。追蹤會帶來額外開銷。每一個被擷取的系統呼叫都需要額外處理時間。在繁忙伺服器上,這種開銷可能會明顯拖慢被追蹤程序。可以使用 -e trace= 之類的篩選器來限制擷取範圍,從而同時降低效能影響與輸出體積。Linux 系統管理員通常都應盡量進行精細篩選。
追蹤程序需要什麼權限?
你需要 root 權限,或使用與目標程序相同的使用者帳號。出於安全原因,Linux 會限制對 ptrace() 的存取。如果權限不足,strace 會回傳錯誤。追蹤其他使用者擁有的服務時,請以 root 身分執行 strace,或使用 sudo。
我可以同時追蹤多個程序嗎?
可以,使用 -f 選項即可追蹤子程序。這樣可以同時擷取主程序及其所有 worker 的系統呼叫。輸出中的每一行都會顯示發起該呼叫的程序 PID。這種方法非常適合那些會建立多個 worker 的伺服器程式。Linux 伺服器通常會同時執行許多 worker 程序。
