0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內(nèi)不再提示

strace是什么 怎樣使用它

Linux愛好者 ? 來源:Linux愛好者 ? 作者:有心故我在 ? 2020-11-17 18:16 ? 次閱讀

什么是strace?

strace是一個非常簡單的工具,它可以跟蹤系統(tǒng)調(diào)用的執(zhí)行。最簡單的方式,它可以從頭到尾跟蹤binary的執(zhí)行,然后以一行文本輸出系統(tǒng)調(diào)用的名字,參數(shù)和返回值。

其實它可以做的更多:

可以對特定的系統(tǒng)調(diào)用或者幾組系統(tǒng)調(diào)用進行過濾

可以通過統(tǒng)計特定系統(tǒng)調(diào)用的調(diào)用次數(shù)、耗費的時間、成功和失敗的次數(shù)來配置(profile)系統(tǒng)調(diào)用的使用 I

跟蹤發(fā)送給進程的信號

可以通過pid附著(attach)到任何運行的進程

如果你使用的是其它Unix系統(tǒng),它類似于"truss"。其它更復雜的是Sun的Dtrace.

怎么使用它

1) 找出程序在startup的時候讀取的哪個config文件?

有沒有嘗過解決為什么某些程序不讀去你認為它應該讀取的config文件的問題?

$ strace php 2>&1 | grep php.ini open("/usr/local/bin/php.ini", O_RDONLY) = -1 ENOENT (No such file or directory) open("/usr/local/lib/php.ini", O_RDONLY) = 4 lstat64("/usr/local/lib/php.ini", {st_mode=S_IFLNK|0777, st_size=27, ...}) = 0 readlink("/usr/local/lib/php.ini", "/usr/local/Zend/etc/php.ini", 4096) = 27 lstat64("/usr/local/Zend/etc/php.ini", {st_mode=S_IFREG|0664, st_size=40971, ...}) = 0

可以看出這個版本的PHP從/usr/local/lib/php.init讀取config文件(但是先嘗試/usr/locl/bin)

如果只關心特定的系統(tǒng)調(diào)用,有更精致的方法

$ strace -e open php 2>&1 | grep php.ini open("/usr/local/bin/php.ini", O_RDONLY) = -1 ENOENT (No such file or directory) open("/usr/local/lib/php.ini", O_RDONLY) = 4

相同的方法適用于很多其它類似的問題。比如說,安裝了不同版本的library,不確定實際上加載了哪一個版本。

-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...

options: trace, abbrev, verbose, raw, signal, read, write

2) 為什么這個程序沒有打開我的文件?

是否曾經(jīng)碰到過一個程序拒絕讀取它沒有權限的文件,但是你發(fā)誓原因是它沒有真正找到那個文件?對程序跟蹤open,access調(diào)用,注意失敗的情況

$ strace -e open,access 2>&1 | grep your-filename

3) 某個進程現(xiàn)在在做什么?

某個進程突然占用了很多CPU? 或者某個進程看起來像hanging了?

找到對應的pid,然后

hang:

懸掛,掛起的意思

就是一個進程被暫時停止執(zhí)行.

root@dev:~# strace -p 15427 Process 15427 attached - interrupt to quit futex(0x402f4900, FUTEX_WAIT, 2, NULL Process15427detached

嗯,這個例子里面,它在調(diào)用futex()的時候掛起了。

"strace -p"非常有用,它減少了很多猜測工作,也不需要重新啟動應用。

-p pid -- trace process with process id PID, may be repeated

4) 是誰偷走了時間?

你可以重新編譯app,打開profiling,以獲取精確的信息。但是通常利用strace附著(attach)一個進程以快速地看一下當前時間花費在哪里非常有用??梢钥聪率欠?0%的CPU用在真正的工作,或者用在其它方面了。

root@dev:~# strace -c -p 11084 Process 11084 attached - interrupt to quit Process 11084 detached % time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ---------------- 94.59 0.001014 48 21 select 2.89 0.000031 1 21 getppid 2.52 0.000027 1 21 time ------ ----------- ----------- --------- --------- ---------------- 100.00 0.001072 63 total root@dev:~#

-c -- count time, calls, and errors for each syscall and report summary

-C -- like -c but also print regular output

在執(zhí)行strace -c -p命令以后,等到你關注的時間到了后,按ctrl-c退出,strace會列出如上的profiling數(shù)據(jù)。

在這個例子中,程序花了絕大部分時間在等待select()。它在每一個slect()調(diào)用這件調(diào)用getpid()和time(),這是一種典型的事件循環(huán)。

你也可以運行"start to finish",這里是"ls"

root@dev:~# strace -c >/dev/null ls % time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ---------------- 23.62 0.000205 103 2 getdents64 18.78 0.000163 15 11 1 open 15.09 0.000131 19 7 read 12.79 0.000111 7 16 old_mmap 7.03 0.000061 6 11 close 4.84 0.000042 11 4 munmap 4.84 0.000042 11 4 mmap2 4.03 0.000035 6 6 6 access 3.80 0.000033 3 11 fstat64 1.38 0.000012 3 4 brk 0.92 0.000008 3 3 3 ioctl 0.69 0.000006 6 1 uname 0.58 0.000005 5 1 set_thread_area 0.35 0.000003 3 1 write 0.35 0.000003 3 1 rt_sigaction 0.35 0.000003 3 1 fcntl64 0.23 0.000002 2 1 getrlimit 0.23 0.000002 2 1 set_tid_address 0.12 0.000001 1 1 rt_sigprocmask ------ ----------- ----------- --------- --------- ---------------- 100.00 0.000868 87 10 total

正如你的預期,它耗費了大部分時間在兩次調(diào)用來讀取目錄條目上(因為運行于一個小的目錄上,所有只有兩次)

5) 為什么 無法連接到服務器?

調(diào)試進程無法連接到遠端服務器有時候是件非常頭痛的事。DNS會失敗,connect會掛起,server有可能返回一些意料之外的數(shù)據(jù)。

可以使用tcpdump來分析這些情況,它是一個非常棒的工作。但是有時候你strace可以給你更簡單,耿直借的角度,因為strace只返回你的進程相關的系統(tǒng)調(diào)用產(chǎn)生的數(shù)據(jù)。

如果你要從100個連接到統(tǒng)一個數(shù)據(jù)服務器的運行進程里面找出一個連接所做的事情,用strace就比tcpdump簡單得多。

下面是跟蹤"nc"連接到www.news.com 80端口的例子

$ strace -e poll,select,connect,recvfrom,sendto nc www.news.com 80 sendto(3, "24