strace是 Linux 的诊断、调试和教学用户空间实用程序。它用于监视和篡改进程和 Linux 内核之间的交互,包括系统调用、信号传递和进程状态的更改。
系统管理员、诊断员和故障处理者会发现,解决源不易可用的程序的问题非常宝贵,因为它们不需要重新编译以跟踪它们。
层的操作是由被称为ptrace的内核功能使。
一些功能
附加到已正在运行的进程。
$ strace -p 26380
strace: Process 26380 attached
...
按系统调用类型进行筛选。
-e trace=%desc Trace all file descriptor related system calls.
%file Trace all system calls which take a file name as an argument.
%fstat Trace fstat and fstatat syscall variants.
%fstatfs Trace fstatfs, fstatfs64, fstatvfs, osf_fstatfs, and osf_fstatfs64 system calls.
%ipc Trace all IPC related system calls.
%lstat Trace lstat syscall variants.
%memory Trace all memory mapping related system calls.
%network Trace all the network related system calls.
%process Trace all system calls which involve process management.
%pure Trace syscalls that always succeed and have no arguments.
%signal Trace all signal related system calls.
%stat Trace stat syscall variants.
%statfs Trace statfs, statfs64, statvfs, osf_statfs, and osf_statfs64 system calls.
%%stat Trace syscalls used for requesting file status.
%%statfs Trace syscalls related to file system statistics.
仅跟踪系统调用访问给定路径。
$ strace -P /etc/ld.so.cache ls /var/empty
open("/etc/ld.so.cache", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=22446, ...}) = 0
mmap(NULL, 22446, PROT_READ, MAP_PRIVATE, 3, 0) = 0x2b7ac2ba9000
close(3) = 0
+++ exited with 0 +++
对从/写入文件描述符读取的所有数据执行完整的十六进制和 ASCII 转储。
$ strace -ewrite=1 -e trace=sendmsg ./recvmsg > /dev/null
sendmsg(1, {msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base="012", iov_len=3},
{iov_base="34567", iov_len=5}, {iov_base="89abcde", iov_len=7}], msg_iovlen=3,
msg_controllen=0, msg_flags=0}, 0) = 15
* 3 bytes in buffer 0
| 00000 30 31 32 012 |
* 5 bytes in buffer 1
| 00000 33 34 35 36 37 34567 |
* 7 bytes in buffer 2
| 00000 38 39 61 62 63 64 65 89abcde |
+++ exited with 0 +++
执行系统呼叫故障注入。
$ strace -e trace=open -e fault=open cat
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = -1 ENOSYS (Function not implemented) (INJECTED)
open("/lib/x86_64-linux-gnu/tls/x86_64/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOSYS (Function not implemented) (INJECTED)
open("/lib/x86_64-linux-gnu/tls/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOSYS (Function not implemented) (INJECTED)
open("/lib/x86_64-linux-gnu/x86_64/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOSYS (Function not implemented) (INJECTED)
open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOSYS (Function not implemented) (INJECTED)
cat: error while loading shared libraries: libc.so.6: cannot open shared object file: Error 38
+++ exited with 127 +++
计算每个系统调用的时间、调用和错误。
$ strace -c ls > /dev/null
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
89.76 0.008016 4 1912 getdents
8.71 0.000778 0 11778 lstat
0.81 0.000072 0 8894 write
0.60 0.000054 0 943 open
0.11 0.000010 0 942 close
0.00 0.000000 0 1 read
0.00 0.000000 0 944 fstat
0.00 0.000000 0 8 mmap
0.00 0.000000 0 4 mprotect
0.00 0.000000 0 1 munmap
0.00 0.000000 0 7 brk
0.00 0.000000 0 3 3 access
0.00 0.000000 0 1 execve
0.00 0.000000 0 1 sysinfo
0.00 0.000000 0 1 arch_prctl
------ ----------- ----------- --------- --------- ----------------
100.00 0.008930 25440 3 total