天天看點

strace指令筆記

strace 可以跟蹤系統調用和程式收到的信号。

根據man strace 說明:

In the simplest case strace runs the specified command until it exits. It intercepts and records the system calls which are called by a process and the signals which are received by a process. The name of each system call, its arguments and its return value are printed on standard error or to the file specified with the -o option.

   strace  is  a useful diagnostic, instructional, and debugging tool.  System administrators, diagnosticians and

trouble-shooters will find it invaluable for solving problems with programs for which the source is not  read‐

   ily  available  since  they  do  not  need to be recompiled in order to trace them.  Students, hackers and the

   overly-curious will find that a great deal can be learned about a system and its system calls by tracing  even

   ordinary  programs.   And  programmers will find that since system calls and signals are events that happen at

   the user/kernel interface, a close examination of this boundary is  very  useful  for  bug  isolation,  sanity

   checking and attempting to capture race conditions.

簡單使用:

$ strace ls /tmp
execve("/usr/bin/ls", ["ls", "/tmp"], 0x7ffc3d196ea8 /* 55 vars */) = 0
brk(NULL)                               = 0x55f3cd933000
arch_prctl(0x3001 /* ARCH_??? */, 0x7fff7fe638b0) = -1 EINVAL (Invalid argument)
....
)      = 17
close(1)                                = 0
close(2)                                = 0
exit_group(0)                           = ?
+++ exited with 0 +++
           

可以看出,簡單的指令也是執行了大量的系統調用。

strace将結果輸出到stderr中:

$ strace cat  /dev/null 2>&1  | grep /dev/null
execve("/usr/bin/cat", ["cat", "/dev/null"], 0x7fff0d14bed8 /* 55 vars */) = 0
openat(AT_FDCWD, "/dev/null", O_RDONLY) = 3
           

這一行: openat(AT_FDCWD, "/dev/null", O_RDONLY) = 3

顯示strace的核心内容就是 各種系統調用 參數 傳回值

除了系統調用,還有收到的信号:

strace sleep 666
           

會阻塞在sleep

如果kill掉這個程序,就會顯示程序收到一 SIGTERM的信号而終止:

-- SIGTERM {si_signo=SIGTERM, si_code=SI_USER, si_pid=979, si_uid=1000} ---
+++ killed by SIGTERM +++
[1] 970 terminated strace sleep 666
           

strace 簡單的代碼:

$ strace python hello.py 2>&1 | grep hello 
execve("/usr/bin/python", ["python", "hello.py"], 0x7fff74efee28 /* 55 vars */) = 0
newfstatat(AT_FDCWD, "/home/blue/pycode/hello.py", {st_mode=S_IFREG|0644, st_size=15, ...}, 0) = 0
openat(AT_FDCWD, "/home/blue/pycode/hello.py", O_RDONLY|O_CLOEXEC) = 3
newfstatat(AT_FDCWD, "/home/blue/pycode/hello.py", {st_mode=S_IFREG|0644, st_size=15, ...}, 0) = 0
readlink("hello.py", 0x7ffe10d730b0, 4096) = -1 EINVAL (Invalid argument)
readlink("/home/blue/pycode/hello.py", 0x7ffe10d72830, 1023) = -1 EINVAL (Invalid argument)
openat(AT_FDCWD, "/home/blue/pycode/hello.py", O_RDONLY) = 3
read(3, "print(\"hello\")\n", 4096)     = 15
read(3, "print(\"hello\")\n", 4096)     = 15
write(1, "hello\n", 6hello
           

可以看出,簡單的代碼也是進行了很多系統調用

對不同的語言hello程式統計系統調用多少情況:

$ strace ./a.out 2>&1 | wc -l
38
$ strace  python hello.py 2>&1| wc -l
1688
$ strace java Hello 2>&1 | wc -l
229
           

可以看出,越低級的語言,調用的越少,性能也越高。

一些參數:

-c 顯示不同系統調用的統計

-t 和 -tt 以及 -ttt 會輸出不同精度的系統調用時間

-T 輸出每個系統調用花費的時間

-i 輸出指令的指針位址

-e trace=(file, network, process)

統計一個程序的網絡調用資訊:

strace -c -e trace=network -p 295141
           

繼續閱讀