天天看点

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
           

继续阅读