strace 可以解決什麼問題?
昨天我 在 Twitter 上詢問大家用 strace 解決了什麼問題?,和往常一樣,大家真的是給出了自己的答案! 我收到了大約 200 個答案,然後花了很多時間手動將它們歸為 9 類。
這些解決的問題都是關於尋找程序依賴的文件、找出程序卡住或慢的原因、或者找出程序失敗的原因。這些總體上與我自己使用 strace
的內容相吻合,但也有一些我沒有想到的東西!
我不打算在這篇文章里解釋什麼是 strace
,但我有一本 關於它的免費雜誌 和 一個講座 以及 很多博文。
問題 1:配置文件在哪裡?
最受歡迎的問題是「這個程序有一個配置文件,但我不知道它在哪裡」。這可能也是我最常使用 strace
解決的問題,因為這是個很簡單的問題。
這很好,因為一個程序有一百萬種方法來記錄它的配置文件在哪裡(在手冊頁、網站上、--help
等),但只有一種方法可以讓它真正打開它(用系統調用!)。
問題 2:這個程序還依賴什麼文件?
你也可以使用 strace
來查找程序依賴的其他類型的文件,比如:
- 動態鏈接庫(「為什麼我的程序載入了這個錯誤版本的
.so
文件?"),比如 我在 2014 年調試的這個 ruby 問題 - 它在哪裡尋找它的 Ruby gem(Ruby 出現了幾次這種情況!)
- SSL 根證書
- 遊戲的存檔文件
- 一個閉源程序的數據文件
- 哪些 node_modules 文件沒有被使用
問題 3:為什麼這個程序會掛掉?
你有一個程序,它只是坐在那裡什麼都不做,這是怎麼回事?這個問題特別容易回答,因為很多時候你只需要運行 strace -p PID
,看看當前運行的是什麼系統調用。你甚至不需要看幾百行的輸出。
答案通常是「正在等待某種 I/O」。「為什麼會卡住」的一些可能的答案(雖然還有很多!):
- 它一直在輪詢
select()
- 正在
wait()
等待一個子進程完成 - 它在向某個沒有響應的東西發出網路請求
- 正在進行
write()
,但由於緩衝區已滿而被阻止。 - 它在 stdin 上做
read()
,等待輸入。
有人還舉了一個很好的例子,用 strace
調試一個卡住的 df
命令:「用 strace df -h
你可以找到卡住的掛載,然後卸載它」。
問題 4:這個程序卡住了嗎?
這是上一個問題的變種:有時一個程序運行的時間比你預期的要長,你只是想知道它是否卡住了,或者它是否還在繼續進行。
只要程序在運行過程中進行系統調用,用 strace
就可以超簡單地回答這個問題:只需 strace
它,看看它是否在進行新的系統調用!
問題 5:為什麼這個程序很慢?
你可以使用 strace
作為一種粗略的剖析工具:strace -t
會顯示每次系統調用的時間戳,這樣你就可以尋找大的漏洞,找到罪魁禍首。
以下是 Twitter 上 9 個人使用 strace
調試「為什麼這個程序很慢?」的小故事。
- 早在 2000 年,我幫助支持的一個基於 Java 的網站在適度的負載下奄奄一息:頁面載入緩慢,甚至完全載入不出來。我們對 J2EE 應用伺服器進行了測試,發現它每次只讀取一個類文件。開發人員沒有使用 BufferedReader,這是典型的 Java 錯誤。
- 優化應用程序的啟動時間……運行
strace
可以讓人大開眼界,因為有大量不必要的文件系統交互在進行(例如,在同一個配置文件上反覆打開/讀取/關閉;在一個緩慢的 NFS 掛載上載入大量的字體文件,等等)。 - 問自己為什麼在 PHP 中從會話文件中讀取(通常是小於 100 位元組)非常慢。結果發現一些
flock
系統調用花了大約 60 秒。 - 一個程序表現得異常緩慢。使用
strace
找出它在每次請求時,通過從/dev/random
讀取數據並耗盡熵來重新初始化其內部偽隨機數發生器。 - 我記得最近一件事是連接到一個任務處理程序,看到它有多少網路調用(這是意想不到的)。
strace
顯示它打開/讀取同一個配置文件數千次。- 伺服器隨機使用 100% 的 CPU 時間,實際流量很低。原來是碰到打開文件數限制,接受一個套接字時,得到 EMFILE 錯誤而沒有報告,然後一直重試。
- 一個工作流運行超慢,但是沒有日誌,結果它做一個 POST 請求花了 30 秒而超時,然後重試了 5 次……結果後台服務不堪重負,但是也沒有可視性。
- 使用
strace
注意到gethostbyname()
需要很長時間才能返回(你不能直接看到gethostbyname
,但你可以看到strace
中的 DNS 數據包)
問題 6:隱藏的許可權錯誤
有時候程序因為一個神秘的原因而失敗,但問題只是有一些它沒有許可權打開的文件。在理想的世界裡,程序會報告這些錯誤(「Error opening file /dev/whatever: permission denied」),當然這個世界並不完美,所以 strace
真的可以幫助解決這個問題!
這其實是我最近使用 strace
做的事情。我使用了一台 AxiDraw 繪圖儀,當我試圖啟動它時,它列印出了一個難以理解的錯誤信息。我 strace
它,結果發現我的用戶沒有許可權打開 USB 設備。
問題 7:正在使用什麼命令行參數?
有時候,一個腳本正在運行另一個程序,你想知道它傳遞的是什麼命令行標誌!
幾個來自 Twitter 的例子。
- 找出實際上是用來編譯代碼的編譯器標誌
- 由於命令行太長,命令失敗了
問題 8:為什麼這個網路連接失敗?
基本上,這裡的目標是找到網路連接的域名 / IP 地址。你可以通過 DNS 請求來查找域名,或者通過 connect
系統調用來查找 IP。
一般來說,當 tcpdump
因為某些原因不能使用或者只是因為比較熟悉 strace
時,就經常會使用 strace
調試網路問題。
問題 9:為什麼這個程序以一種方式運行時成功,以另一種方式運行時失敗?
例如:
- 同樣的二進位程序在一台機器上可以運行,在另一台機器上卻失敗了
- 可以運行,但被 systemd 單元文件生成時失敗
- 可以運行,但以
su - user /some/script
的方式運行時失敗 - 可以運行,作為 cron 作業運行時失敗
能夠比較兩種情況下的 strace
輸出是非常有用的。雖然我在調試「以我的用戶身份工作,而在同一台計算機上以不同方式運行時卻失敗了」時,第一步是「看看我的環境變數」。
我在做什麼:慢慢地建立一些挑戰
我之所以會想到這個問題,是因為我一直在慢慢地進行一些挑戰,以幫助人們練習使用 strace
和其他命令行工具。我的想法是,給你一個問題,一個終端,你可以自由地以任何方式解決它。
所以我的目標是用它來建立一些你可以用 strace
解決的練習題,這些練習題反映了人們在現實生活中實際使用它解決的問題。
就是這樣!
可能還有更多的問題可以用 strace
解決,我在這裡還沒有講到,我很樂意聽到我錯過了什麼!
我真的很喜歡看到很多相同的用法一次又一次地出現:至少有 20 個不同的人回答說他們使用 strace
來查找配置文件。而且和以往一樣,我覺得這樣一個簡單的工具(「跟蹤系統調用!」)可以用來解決這麼多不同類型的問題,真的很令人高興。
via: https://jvns.ca/blog/2021/04/03/what-problems-do-people-solve-with-strace/
作者:Julia Evans 選題:lujun9972 譯者:wxy 校對:wxy
本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive